1. Project Clover database Sat Apr 27 2024 21:29:13 CDT
  2. Package net.bytebuddy.agent.builder

File AgentBuilder.java

 

Coverage histogram

../../../../img/srcFileCovDistChart9.png
81% of files have more coverage

Code metrics

206
1,204
399
95
6,769
3,792
551
0.46
3.02
4.2
1.38

Classes

Class Line # Actions
AgentBuilder 79 0 - 0 0
-1.0 -
AgentBuilder.Matchable 580 0 - 0 0
-1.0 -
AgentBuilder.Matchable.AbstractBase 663 6 0% 6 0
1.0100%
AgentBuilder.Ignored 704 0 - 0 0
-1.0 -
AgentBuilder.Identified 713 0 - 0 0
-1.0 -
AgentBuilder.Identified.Narrowable 727 0 - 0 0
-1.0 -
AgentBuilder.Identified.Extendable 736 0 - 0 0
-1.0 -
AgentBuilder.RawMatcher 761 0 - 0 0
-1.0 -
AgentBuilder.RawMatcher.Conjunction 786 13 0% 8 0
1.0100%
AgentBuilder.RawMatcher.Disjunction 846 13 0% 8 0
1.0100%
AgentBuilder.RawMatcher.ForElementMatchers 908 10 0% 5 0
1.0100%
AgentBuilder.TypeStrategy 981 0 - 0 0
-1.0 -
AgentBuilder.TypeStrategy.Default 1000 4 0% 4 0
1.0100%
AgentBuilder.Transformer 1072 0 - 0 0
-1.0 -
AgentBuilder.Transformer.NoOp 1089 2 0% 2 0
1.0100%
AgentBuilder.Transformer.Compound 1111 7 0% 5 0
1.0100%
AgentBuilder.TypeLocator 1158 0 - 0 0
-1.0 -
AgentBuilder.TypeLocator.Default 1173 3 0% 3 0
1.0100%
AgentBuilder.TypeLocator.ClassLoading 1221 3 0% 3 0
1.0100%
AgentBuilder.TypeLocator.WithTypePoolCache 1270 9 0% 7 4
0.764705976.5%
AgentBuilder.TypeLocator.WithTypePoolCache.Simple 1316 21 0% 12 0
1.0100%
AgentBuilder.TypeLocator.WithTypePoolCache.Simple.BootstrapClassLoaderMarker 1381 1 0% 1 2
0.00%
AgentBuilder.TypeLocator.WithTypePoolCache.Simple.BootstrapClassLoaderMarker.CreationAction 1396 1 0% 1 0
1.0100%
AgentBuilder.Listener 1411 0 - 0 0
-1.0 -
AgentBuilder.Listener.NoOp 1454 1 0% 5 0
1.0100%
AgentBuilder.Listener.Adapter 1490 0 0% 4 0
1.0100%
AgentBuilder.Listener.StreamWriting 1517 11 0% 10 0
1.0100%
AgentBuilder.Listener.ModuleReadEdgeCompleting 1599 26 0% 17 12
0.7575%
AgentBuilder.Listener.Compound 1697 13 0% 9 0
1.0100%
AgentBuilder.InitializationStrategy 1774 0 - 0 0
-1.0 -
AgentBuilder.InitializationStrategy.Dispatcher 1786 0 - 0 0
-1.0 -
AgentBuilder.InitializationStrategy.Dispatcher.InjectorFactory 1808 0 - 0 0
-1.0 -
AgentBuilder.InitializationStrategy.NoOp 1822 3 0% 4 0
1.0100%
AgentBuilder.InitializationStrategy.SelfInjection 1855 4 0% 4 0
1.0100%
AgentBuilder.InitializationStrategy.SelfInjection.Dispatcher 1897 4 0% 4 0
1.0100%
AgentBuilder.InitializationStrategy.SelfInjection.Dispatcher.Split 1932 21 0% 8 2
0.941176594.1%
AgentBuilder.InitializationStrategy.SelfInjection.Dispatcher.Lazy 1985 6 0% 5 2
0.8461538684.6%
AgentBuilder.InitializationStrategy.SelfInjection.Dispatcher.Eager 2016 10 0% 5 2
0.8823529588.2%
AgentBuilder.InitializationStrategy.SelfInjection.Dispatcher.InjectingInitializer 2051 20 0% 9 0
1.0100%
AgentBuilder.InitializationStrategy.SelfInjection.NexusAccessor 2140 16 0% 6 1
0.9595%
AgentBuilder.InitializationStrategy.SelfInjection.NexusAccessor.Dispatcher 2241 0 - 0 0
-1.0 -
AgentBuilder.InitializationStrategy.SelfInjection.NexusAccessor.Dispatcher.Available 2256 8 0% 7 2
0.8461538684.6%
AgentBuilder.InitializationStrategy.SelfInjection.NexusAccessor.Dispatcher.Unavailable 2310 5 0% 5 0
1.0100%
AgentBuilder.InitializationStrategy.SelfInjection.NexusAccessor.InitializationAppender 2354 10 0% 8 0
1.0100%
AgentBuilder.InitializationStrategy.Minimal 2422 13 0% 6 0
1.0100%
AgentBuilder.DescriptionStrategy 2467 0 - 0 0
-1.0 -
AgentBuilder.DescriptionStrategy.Default 2493 5 0% 6 0
1.0100%
AgentBuilder.InstallationStrategy 2566 0 - 0 0
-1.0 -
AgentBuilder.InstallationStrategy.Default 2581 4 0% 3 0
1.0100%
AgentBuilder.RedefinitionStrategy 2616 16 0% 14 2
0.937593.8%
AgentBuilder.RedefinitionStrategy.Collector 2789 0 - 0 0
-1.0 -
AgentBuilder.RedefinitionStrategy.Collector.ForRedefinition 2817 12 0% 4 3
0.880%
AgentBuilder.RedefinitionStrategy.Collector.ForRedefinition.Cumulative 2880 4 0% 4 0
1.0100%
AgentBuilder.RedefinitionStrategy.Collector.ForRedefinition.Chunked 2910 9 0% 5 0
1.0100%
AgentBuilder.RedefinitionStrategy.Collector.ForRedefinition.Entry 2948 11 0% 9 0
1.0100%
AgentBuilder.RedefinitionStrategy.Collector.ForRetransformation 3009 3 0% 2 0
1.0100%
AgentBuilder.RedefinitionStrategy.Collector.ForRetransformation.Cumulative 3044 4 0% 4 0
1.0100%
AgentBuilder.RedefinitionStrategy.Collector.ForRetransformation.Chunked 3074 9 0% 5 0
1.0100%
AgentBuilder.LambdaInstrumentationStrategy 3115 16 0% 13 3
0.990%
AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory 3233 31 0% 11 5
0.891304489.1%
AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.ConstructorImplementation 3395 4 0% 4 0
1.0100%
AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.ConstructorImplementation.Appender 3432 10 0% 5 0
1.0100%
AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.FactoryImplementation 3487 3 0% 3 0
1.0100%
AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.FactoryImplementation.Appender 3512 5 0% 5 0
1.0100%
AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.LambdaMethodImplementation 3562 14 0% 9 13
0.4583333445.8%
AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.LambdaMethodImplementation.Appender 3629 23 0% 8 0
1.0100%
AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.SerializationImplementation 3715 29 0% 10 1
0.97435997.4%
AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.BridgeMethodImplementation 3848 14 0% 9 4
0.833333383.3%
AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.BridgeMethodImplementation.Appender 3909 5 0% 6 4
0.666666766.7%
AgentBuilder.LambdaInstrumentationStrategy.MetaFactoryRedirection 3998 133 0% 2 0
1.0100%
AgentBuilder.LambdaInstrumentationStrategy.AlternativeMetaFactoryRedirection 4208 225 0% 2 0
1.0100%
AgentBuilder.Default 4465 99 0% 54 26
0.8300653783%
AgentBuilder.Default.BootstrapInjectionStrategy 5132 0 - 0 0
-1.0 -
AgentBuilder.Default.BootstrapInjectionStrategy.Disabled 5145 2 0% 2 0
1.0100%
AgentBuilder.Default.BootstrapInjectionStrategy.Enabled 5166 13 0% 8 0
1.0100%
AgentBuilder.Default.NativeMethodStrategy 5222 0 - 0 0
-1.0 -
AgentBuilder.Default.NativeMethodStrategy.Disabled 5249 4 0% 4 0
1.0100%
AgentBuilder.Default.NativeMethodStrategy.ForPrefix 5280 12 0% 10 0
1.0100%
AgentBuilder.Default.Transformation 5349 0 - 0 0
-1.0 -
AgentBuilder.Default.Transformation.Resolution 5372 0 - 0 0
-1.0 -
AgentBuilder.Default.Transformation.Resolution.Sort 5422 3 0% 3 0
1.0100%
AgentBuilder.Default.Transformation.Resolution.Decoratable 5472 0 - 0 0
-1.0 -
AgentBuilder.Default.Transformation.Resolution.Unresolved 5486 19 0% 15 6
0.8461538684.6%
AgentBuilder.Default.Transformation.Ignored 5576 2 0% 2 0
1.0100%
AgentBuilder.Default.Transformation.Simple 5602 10 0% 8 1
0.9473684494.7%
AgentBuilder.Default.Transformation.Simple.Resolution 5673 29 0% 20 7
0.8793103787.9%
AgentBuilder.Default.Transformation.Simple.Resolution.BootstrapClassLoaderCapableInjectorFactory 5817 17 0% 13 4
0.888888988.9%
AgentBuilder.Default.Transformation.Compound 5900 19 0% 9 2
0.9292%
AgentBuilder.Default.ExecutingTransformer 5979 48 0% 15 5
0.9193548691.9%
AgentBuilder.Default.ExecutingTransformer.Factory 6250 0 - 0 0
-1.0 -
AgentBuilder.Default.ExecutingTransformer.Factory.ForJava9CapableVm 6284 14 0% 11 3
0.869565287%
AgentBuilder.Default.ExecutingTransformer.Factory.ForLegacyVm 6359 2 0% 2 2
0.550%
AgentBuilder.Default.Delegator 6404 32 0% 32 50
0.2187521.9%
AgentBuilder.Default.Ignoring 6582 10 0% 8 0
1.0100%
AgentBuilder.Default.Transforming 6663 16 0% 11 1
0.9642857396.4%
 

Contributing tests

This file is covered by 272 tests. .

Source view

1    package net.bytebuddy.agent.builder;
2   
3    import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4    import net.bytebuddy.ByteBuddy;
5    import net.bytebuddy.ClassFileVersion;
6    import net.bytebuddy.asm.AsmVisitorWrapper;
7    import net.bytebuddy.description.field.FieldDescription;
8    import net.bytebuddy.description.method.MethodDescription;
9    import net.bytebuddy.description.method.ParameterDescription;
10    import net.bytebuddy.description.modifier.*;
11    import net.bytebuddy.description.type.TypeDescription;
12    import net.bytebuddy.dynamic.ClassFileLocator;
13    import net.bytebuddy.dynamic.DynamicType;
14    import net.bytebuddy.dynamic.loading.ClassInjector;
15    import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
16    import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
17    import net.bytebuddy.dynamic.scaffold.InstrumentedType;
18    import net.bytebuddy.dynamic.scaffold.inline.MethodNameTransformer;
19    import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
20    import net.bytebuddy.implementation.ExceptionMethod;
21    import net.bytebuddy.implementation.Implementation;
22    import net.bytebuddy.implementation.LoadedTypeInitializer;
23    import net.bytebuddy.implementation.MethodCall;
24    import net.bytebuddy.implementation.auxiliary.AuxiliaryType;
25    import net.bytebuddy.implementation.bytecode.*;
26    import net.bytebuddy.implementation.bytecode.assign.Assigner;
27    import net.bytebuddy.implementation.bytecode.assign.TypeCasting;
28    import net.bytebuddy.implementation.bytecode.collection.ArrayFactory;
29    import net.bytebuddy.implementation.bytecode.constant.ClassConstant;
30    import net.bytebuddy.implementation.bytecode.constant.IntegerConstant;
31    import net.bytebuddy.implementation.bytecode.constant.NullConstant;
32    import net.bytebuddy.implementation.bytecode.constant.TextConstant;
33    import net.bytebuddy.implementation.bytecode.member.FieldAccess;
34    import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
35    import net.bytebuddy.implementation.bytecode.member.MethodReturn;
36    import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
37    import net.bytebuddy.matcher.ElementMatcher;
38    import net.bytebuddy.pool.TypePool;
39    import net.bytebuddy.utility.JavaConstant;
40    import net.bytebuddy.utility.JavaModule;
41    import net.bytebuddy.utility.JavaType;
42    import org.objectweb.asm.Label;
43    import org.objectweb.asm.MethodVisitor;
44    import org.objectweb.asm.Opcodes;
45    import org.objectweb.asm.Type;
46   
47    import java.io.*;
48    import java.lang.instrument.ClassDefinition;
49    import java.lang.instrument.ClassFileTransformer;
50    import java.lang.instrument.Instrumentation;
51    import java.lang.instrument.UnmodifiableClassException;
52    import java.lang.reflect.Constructor;
53    import java.lang.reflect.InvocationTargetException;
54    import java.lang.reflect.Method;
55    import java.security.AccessControlContext;
56    import java.security.AccessController;
57    import java.security.PrivilegedAction;
58    import java.security.ProtectionDomain;
59    import java.util.*;
60    import java.util.concurrent.Callable;
61    import java.util.concurrent.ConcurrentMap;
62    import java.util.concurrent.atomic.AtomicInteger;
63   
64    import static net.bytebuddy.matcher.ElementMatchers.*;
65   
66    /**
67    * <p>
68    * An agent builder provides a convenience API for defining a
69    * <a href="http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html">Java agent</a>. By default,
70    * this transformation is applied by rebasing the type if not specified otherwise by setting a
71    * {@link TypeStrategy}.
72    * </p>
73    * <p>
74    * When defining several {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s, the agent builder always
75    * applies the transformers that were supplied with the last applicable matcher. Therefore, more general transformers
76    * should be defined first.
77    * </p>
78    */
 
79    public interface AgentBuilder {
80   
81    /**
82    * Defines the given {@link net.bytebuddy.ByteBuddy} instance to be used by the created agent.
83    *
84    * @param byteBuddy The Byte Buddy instance to be used.
85    * @return A new instance of this agent builder which makes use of the given {@code byteBuddy} instance.
86    */
87    AgentBuilder with(ByteBuddy byteBuddy);
88   
89    /**
90    * Defines the given {@link net.bytebuddy.agent.builder.AgentBuilder.Listener} to be notified by the created agent.
91    * The given listener is notified after any other listener that is already registered. If a listener is registered
92    * twice, it is also notified twice.
93    *
94    * @param listener The listener to be notified.
95    * @return A new instance of this agent builder which creates an agent that informs the given listener about
96    * events.
97    */
98    AgentBuilder with(Listener listener);
99   
100    /**
101    * Defines the use of the given type locator for locating binary data to given class names.
102    *
103    * @param typeLocator The type locator to use.
104    * @return A new instance of this agent builder which uses the given type locator for looking up class files.
105    */
106    AgentBuilder with(TypeLocator typeLocator);
107   
108    /**
109    * Defines how types should be transformed, e.g. if they should be rebased or redefined by the created agent.
110    *
111    * @param typeStrategy The type strategy to use.
112    * @return A new instance of this agent builder which uses the given type strategy.
113    */
114    AgentBuilder with(TypeStrategy typeStrategy);
115   
116    /**
117    * Assures that critical actions are performed using the supplied access control context.
118    *
119    * @param accessControlContext The access control context to be used for performing security critical action.
120    * @return A new instance of this agent builder which uses the given access control context for performing critical actions.
121    */
122    AgentBuilder with(AccessControlContext accessControlContext);
123   
124    /**
125    * Defines a given initialization strategy to be applied to generated types. An initialization strategy is responsible
126    * for setting up a type after it was loaded. This initialization must be performed after the transformation because
127    * a Java agent is only invoked before loading a type. By default, the initialization logic is added to a class's type
128    * initializer which queries a global object for any objects that are to be injected into the generated type.
129    *
130    * @param initializationStrategy The initialization strategy to use.
131    * @return A new instance of this agent builder that applies the given initialization strategy.
132    */
133    AgentBuilder with(InitializationStrategy initializationStrategy);
134   
135    /**
136    * Specifies a strategy for modifying types that were already loaded prior to the installation of this transformer.
137    *
138    * @param redefinitionStrategy The redefinition strategy to apply.
139    * @return A new instance of this agent builder that applies the given redefinition strategy.
140    */
141    AgentBuilder with(RedefinitionStrategy redefinitionStrategy);
142   
143    /**
144    * <p>
145    * Enables or disables management of the JVM's {@code LambdaMetafactory} which is responsible for creating classes that
146    * implement lambda expressions. Without this feature enabled, classes that are represented by lambda expressions are
147    * not instrumented by the JVM such that Java agents have no effect on them when a lambda expression's class is loaded
148    * for the first time.
149    * </p>
150    * <p>
151    * When activating this feature, Byte Buddy instruments the {@code LambdaMetafactory} and takes over the responsibility
152    * of creating classes that represent lambda expressions. In doing so, Byte Buddy has the opportunity to apply the built
153    * class file transformer. If the current VM does not support lambda expressions, activating this feature has no effect.
154    * </p>
155    * <p>
156    * <b>Important</b>: If this feature is active, it is important to release the built class file transformer when
157    * deactivating it. Normally, it is sufficient to call {@link Instrumentation#removeTransformer(ClassFileTransformer)}.
158    * When this feature is enabled, it is however also required to invoke
159    * {@link LambdaInstrumentationStrategy#release(ClassFileTransformer, Instrumentation)}. Otherwise, the executing VMs class
160    * loader retains a reference to the class file transformer what can cause a memory leak.
161    * </p>
162    *
163    * @param lambdaInstrumentationStrategy {@code true} if this feature should be enabled.
164    * @return A new instance of this agent builder where this feature is explicitly enabled or disabled.
165    */
166    AgentBuilder with(LambdaInstrumentationStrategy lambdaInstrumentationStrategy);
167   
168    /**
169    * Specifies a strategy to be used for resolving {@link TypeDescription} for any type handled by the created transformer.
170    *
171    * @param descriptionStrategy The description strategy to use.
172    * @return A new instance of this agent builder that applies the given description strategy.
173    */
174    AgentBuilder with(DescriptionStrategy descriptionStrategy);
175   
176    /**
177    * Specifies an installation strategy that this agent builder applies upon installing an agent.
178    *
179    * @param installationStrategy The installation strategy to be used.
180    * @return A new agent builder that applies the supplied installation strategy.
181    */
182    AgentBuilder with(InstallationStrategy installationStrategy);
183   
184    /**
185    * Enables class injection of auxiliary classes into the bootstrap class loader.
186    *
187    * @param instrumentation The instrumentation instance that is used for appending jar files to the
188    * bootstrap class path.
189    * @param folder The folder in which jar files of the injected classes are to be stored.
190    * @return An agent builder with bootstrap class loader class injection enabled.
191    */
192    AgentBuilder enableBootstrapInjection(Instrumentation instrumentation, File folder);
193   
194    /**
195    * Enables the use of the given native method prefix for instrumented methods. Note that this prefix is also
196    * applied when preserving non-native methods. The use of this prefix is also registered when installing the
197    * final agent with an {@link java.lang.instrument.Instrumentation}.
198    *
199    * @param prefix The prefix to be used.
200    * @return A new instance of this agent builder which uses the given native method prefix.
201    */
202    AgentBuilder enableNativeMethodPrefix(String prefix);
203   
204    /**
205    * Disables the use of a native method prefix for instrumented methods.
206    *
207    * @return A new instance of this agent builder which does not use a native method prefix.
208    */
209    AgentBuilder disableNativeMethodPrefix();
210   
211    /**
212    * Disables injection of auxiliary classes into the bootstrap class path.
213    *
214    * @return A new instance of this agent builder which does not apply bootstrap class loader injection.
215    */
216    AgentBuilder disableBootstrapInjection();
217   
218    /**
219    * <p>
220    * Disables all implicit changes on a class file that Byte Buddy would apply for certain instrumentations. When
221    * using this option, it is no longer possible to rebase a method, i.e. intercepted methods are fully replaced. Furthermore,
222    * it is no longer possible to implicitly apply loaded type initializers for explicitly initializing the generated type.
223    * </p>
224    * <p>
225    * This is equivalent to setting {@link InitializationStrategy.NoOp} and {@link TypeStrategy.Default#REDEFINE_DECLARED_ONLY}
226    * as well as configuring the underlying {@link ByteBuddy} instance to use a {@link net.bytebuddy.implementation.Implementation.Context.Disabled}.
227    * </p>
228    *
229    * @return A new instance of this agent builder that does not apply any implicit changes to the received class file.
230    */
231    AgentBuilder disableClassFormatChanges();
232   
233    /**
234    * Assures that all modules of the supplied types are read by the module of any instrumented type. If the current VM does not support
235    * the Java module system, calling this method has no effect and this instance is returned.
236    *
237    * @param instrumentation The instrumentation instance that is used for adding a module read-dependency.
238    * @param type The types for which to assure their module-visibility from any instrumented class.
239    * @return A new instance of this agent builder that assures the supplied types module visibility.
240    * @see Listener.ModuleReadEdgeCompleting
241    */
242    AgentBuilder assureReadEdgeTo(Instrumentation instrumentation, Class<?>... type);
243   
244    /**
245    * Assures that all supplied modules are read by the module of any instrumented type.
246    *
247    * @param instrumentation The instrumentation instance that is used for adding a module read-dependency.
248    * @param module The modules for which to assure their module-visibility from any instrumented class.
249    * @return A new instance of this agent builder that assures the supplied types module visibility.
250    * @see Listener.ModuleReadEdgeCompleting
251    */
252    AgentBuilder assureReadEdgeTo(Instrumentation instrumentation, JavaModule... module);
253   
254    /**
255    * Assures that all supplied modules are read by the module of any instrumented type.
256    *
257    * @param instrumentation The instrumentation instance that is used for adding a module read-dependency.
258    * @param modules The modules for which to assure their module-visibility from any instrumented class.
259    * @return A new instance of this agent builder that assures the supplied types module visibility.
260    * @see Listener.ModuleReadEdgeCompleting
261    */
262    AgentBuilder assureReadEdgeTo(Instrumentation instrumentation, Collection<? extends JavaModule> modules);
263   
264    /**
265    * Assures that all modules of the supplied types are read by the module of any instrumented type and vice versa.
266    * If the current VM does not support the Java module system, calling this method has no effect and this instance is returned.
267    *
268    * @param instrumentation The instrumentation instance that is used for adding a module read-dependency.
269    * @param type The types for which to assure their module-visibility from and to any instrumented class.
270    * @return A new instance of this agent builder that assures the supplied types module visibility.
271    * @see Listener.ModuleReadEdgeCompleting
272    */
273    AgentBuilder assureReadEdgeFromAndTo(Instrumentation instrumentation, Class<?>... type);
274   
275    /**
276    * Assures that all supplied modules are read by the module of any instrumented type and vice versa.
277    *
278    * @param instrumentation The instrumentation instance that is used for adding a module read-dependency.
279    * @param module The modules for which to assure their module-visibility from and to any instrumented class.
280    * @return A new instance of this agent builder that assures the supplied types module visibility.
281    * @see Listener.ModuleReadEdgeCompleting
282    */
283    AgentBuilder assureReadEdgeFromAndTo(Instrumentation instrumentation, JavaModule... module);
284   
285    /**
286    * Assures that all supplied modules are read by the module of any instrumented type and vice versa.
287    *
288    * @param instrumentation The instrumentation instance that is used for adding a module read-dependency.
289    * @param modules The modules for which to assure their module-visibility from and to any instrumented class.
290    * @return A new instance of this agent builder that assures the supplied types module visibility.
291    * @see Listener.ModuleReadEdgeCompleting
292    */
293    AgentBuilder assureReadEdgeFromAndTo(Instrumentation instrumentation, Collection<? extends JavaModule> modules);
294   
295    /**
296    * <p>
297    * Matches a type being loaded in order to apply the supplied {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s before loading this type.
298    * If several matchers positively match a type only the latest registered matcher is considered for transformation.
299    * </p>
300    * <p>
301    * If this matcher is chained with additional subsequent matchers, this matcher is always executed first whereas the following matchers are
302    * executed in the order of their execution. If any matcher indicates that a type is to be matched, none of the following matchers is still queried.
303    * This behavior can be changed by {@link Identified.Extendable#asDecorator()} where subsequent type matchers are also applied.
304    * </p>
305    * <p>
306    * <b>Note</b>: When applying a matcher, regard the performance implications by {@link AgentBuilder#ignore(ElementMatcher)}. The former
307    * matcher is applied first such that it makes sense to ignore name spaces that are irrelevant to instrumentation. If possible, it is
308    * also recommended, to exclude class loaders such as for example the bootstrap class loader by using
309    * {@link AgentBuilder#type(ElementMatcher, ElementMatcher)} instead.
310    * </p>
311    *
312    * @param typeMatcher An {@link net.bytebuddy.matcher.ElementMatcher} that is applied on the type being loaded that
313    * decides if the entailed {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s should
314    * be applied for that type.
315    * @return A definable that represents this agent builder which allows for the definition of one or several
316    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s to be applied when the given {@code typeMatcher}
317    * indicates a match.
318    */
319    Identified.Narrowable type(ElementMatcher<? super TypeDescription> typeMatcher);
320   
321    /**
322    * <p>
323    * Matches a type being loaded in order to apply the supplied {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s before loading this type.
324    * If several matchers positively match a type only the latest registered matcher is considered for transformation.
325    * </p>
326    * <p>
327    * If this matcher is chained with additional subsequent matchers, this matcher is always executed first whereas the following matchers are
328    * executed in the order of their execution. If any matcher indicates that a type is to be matched, none of the following matchers is still queried.
329    * This behavior can be changed by {@link Identified.Extendable#asDecorator()} where subsequent type matchers are also applied.
330    * </p>
331    * <p>
332    * <b>Note</b>: When applying a matcher, regard the performance implications by {@link AgentBuilder#ignore(ElementMatcher)}. The former
333    * matcher is applied first such that it makes sense to ignore name spaces that are irrelevant to instrumentation. If possible, it
334    * is also recommended, to exclude class loaders such as for example the bootstrap class loader.
335    * </p>
336    *
337    * @param typeMatcher An {@link net.bytebuddy.matcher.ElementMatcher} that is applied on the type being
338    * loaded that decides if the entailed
339    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s should be applied for
340    * that type.
341    * @param classLoaderMatcher An {@link net.bytebuddy.matcher.ElementMatcher} that is applied to the
342    * {@link java.lang.ClassLoader} that is loading the type being loaded. This matcher
343    * is always applied first where the type matcher is not applied in case that this
344    * matcher does not indicate a match.
345    * @return A definable that represents this agent builder which allows for the definition of one or several
346    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s to be applied when both the given
347    * {@code typeMatcher} and {@code classLoaderMatcher} indicate a match.
348    */
349    Identified.Narrowable type(ElementMatcher<? super TypeDescription> typeMatcher, ElementMatcher<? super ClassLoader> classLoaderMatcher);
350   
351    /**
352    * <p>
353    * Matches a type being loaded in order to apply the supplied {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s before loading this type.
354    * If several matchers positively match a type only the latest registered matcher is considered for transformation.
355    * </p>
356    * <p>
357    * If this matcher is chained with additional subsequent matchers, this matcher is always executed first whereas the following matchers are
358    * executed in the order of their execution. If any matcher indicates that a type is to be matched, none of the following matchers is still queried.
359    * This behavior can be changed by {@link Identified.Extendable#asDecorator()} where subsequent type matchers are also applied.
360    * </p>
361    * <p>
362    * <b>Note</b>: When applying a matcher, regard the performance implications by {@link AgentBuilder#ignore(ElementMatcher)}. The former
363    * matcher is applied first such that it makes sense to ignore name spaces that are irrelevant to instrumentation. If possible, it
364    * is also recommended, to exclude class loaders such as for example the bootstrap class loader.
365    * </p>
366    *
367    * @param typeMatcher An {@link net.bytebuddy.matcher.ElementMatcher} that is applied on the type being
368    * loaded that decides if the entailed
369    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s should be applied for
370    * that type.
371    * @param classLoaderMatcher An {@link net.bytebuddy.matcher.ElementMatcher} that is applied to the
372    * {@link java.lang.ClassLoader} that is loading the type being loaded. This matcher
373    * is always applied second where the type matcher is not applied in case that this
374    * matcher does not indicate a match.
375    * @param moduleMatcher An {@link net.bytebuddy.matcher.ElementMatcher} that is applied to the {@link JavaModule}
376    * of the type being loaded. This matcher is always applied first where the class loader and
377    * type matchers are not applied in case that this matcher does not indicate a match. On a JVM
378    * that does not support the Java modules system, this matcher is not applied.
379    * @return A definable that represents this agent builder which allows for the definition of one or several
380    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s to be applied when both the given
381    * {@code typeMatcher} and {@code classLoaderMatcher} indicate a match.
382    */
383    Identified.Narrowable type(ElementMatcher<? super TypeDescription> typeMatcher,
384    ElementMatcher<? super ClassLoader> classLoaderMatcher,
385    ElementMatcher<? super JavaModule> moduleMatcher);
386   
387    /**
388    * <p>
389    * Matches a type being loaded in order to apply the supplied {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s before loading this type.
390    * If several matchers positively match a type only the latest registered matcher is considered for transformation.
391    * </p>
392    * <p>
393    * If this matcher is chained with additional subsequent matchers, this matcher is always executed first whereas the following matchers are
394    * executed in the order of their execution. If any matcher indicates that a type is to be matched, none of the following matchers is still queried.
395    * </p>
396    * <p>
397    * <b>Note</b>: When applying a matcher, regard the performance implications by {@link AgentBuilder#ignore(ElementMatcher)}. The former
398    * matcher is applied first such that it makes sense to ignore name spaces that are irrelevant to instrumentation. If possible, it
399    * is also recommended, to exclude class loaders such as for example the bootstrap class loader.
400    * </p>
401    *
402    * @param matcher A matcher that decides if the entailed {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s should be
403    * applied for a type that is being loaded.
404    * @return A definable that represents this agent builder which allows for the definition of one or several
405    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s to be applied when the given {@code matcher}
406    * indicates a match.
407    */
408    Identified.Narrowable type(RawMatcher matcher);
409   
410    /**
411    * <p>
412    * Excludes any type that is matched by the provided matcher from instrumentation and considers types by all {@link ClassLoader}s.
413    * By default, Byte Buddy does not instrument synthetic types or types that are loaded by the bootstrap class loader.
414    * </p>
415    * <p>
416    * When ignoring a type, any subsequently chained matcher is applied after this matcher in the order of their registration. Also, if
417    * any matcher indicates that a type is to be ignored, none of the following chained matchers is executed.
418    * </p>
419    * <p>
420    * <b>Note</b>: For performance reasons, it is recommended to always include a matcher that excludes as many namespaces
421    * as possible. Byte Buddy can determine a type's name without parsing its class file and can therefore discard such
422    * types with minimal overhead. When a different property of a type - such as for example its modifiers or its annotations
423    * is accessed - Byte Buddy parses the class file lazily in order to allow for such a matching. Therefore, any exclusion
424    * of a name should always be done as a first step and even if it does not influence the selection of what types are
425    * matched. Without changing this property, the class file of every type is being parsed!
426    * </p>
427    * <p>
428    * <b>Warning</b>: If a type is loaded during the instrumentation of the same type, this causes the original call site that loads the type
429    * to remain unbound, causing a {@link LinkageError}. It is therefore important to not instrument types that may be loaded during the application
430    * of a {@link Transformer}. For this reason, it is not recommended to instrument classes of the bootstrap class loader that Byte Buddy might
431    * require for instrumenting a class or to instrument any of Byte Buddy's classes. If such instrumentation is desired, it is important to
432    * assert for each class that they are not loaded during instrumentation.
433    * </p>
434    *
435    * @param typeMatcher A matcher that identifies types that should not be instrumented.
436    * @return A new instance of this agent builder that ignores all types that are matched by the provided matcher.
437    * All previous matchers for ignored types are discarded.
438    */
439    Ignored ignore(ElementMatcher<? super TypeDescription> typeMatcher);
440   
441    /**
442    * <p>
443    * Excludes any type that is matched by the provided matcher and is loaded by a class loader matching the second matcher.
444    * By default, Byte Buddy does not instrument synthetic types, types within a {@code net.bytebuddy.*} package or types that
445    * are loaded by the bootstrap class loader.
446    * </p>
447    * <p>
448    * When ignoring a type, any subsequently chained matcher is applied after this matcher in the order of their registration. Also, if
449    * any matcher indicates that a type is to be ignored, none of the following chained matchers is executed.
450    * </p>
451    * <p>
452    * <b>Note</b>: For performance reasons, it is recommended to always include a matcher that excludes as many namespaces
453    * as possible. Byte Buddy can determine a type's name without parsing its class file and can therefore discard such
454    * types with minimal overhead. When a different property of a type - such as for example its modifiers or its annotations
455    * is accessed - Byte Buddy parses the class file lazily in order to allow for such a matching. Therefore, any exclusion
456    * of a name should always be done as a first step and even if it does not influence the selection of what types are
457    * matched. Without changing this property, the class file of every type is being parsed!
458    * </p>
459    * <p>
460    * <b>Warning</b>: If a type is loaded during the instrumentation of the same type, this causes the original call site that loads the type
461    * to remain unbound, causing a {@link LinkageError}. It is therefore important to not instrument types that may be loaded during the application
462    * of a {@link Transformer}. For this reason, it is not recommended to instrument classes of the bootstrap class loader that Byte Buddy might
463    * require for instrumenting a class or to instrument any of Byte Buddy's classes. If such instrumentation is desired, it is important to
464    * assert for each class that they are not loaded during instrumentation.
465    * </p>
466    *
467    * @param typeMatcher A matcher that identifies types that should not be instrumented.
468    * @param classLoaderMatcher A matcher that identifies a class loader that identifies classes that should not be instrumented.
469    * @return A new instance of this agent builder that ignores all types that are matched by the provided matcher.
470    * All previous matchers for ignored types are discarded.
471    */
472    Ignored ignore(ElementMatcher<? super TypeDescription> typeMatcher, ElementMatcher<? super ClassLoader> classLoaderMatcher);
473   
474    /**
475    * <p>
476    * Excludes any type that is matched by the provided matcher and is loaded by a class loader matching the second matcher.
477    * By default, Byte Buddy does not instrument synthetic types, types within a {@code net.bytebuddy.*} package or types that
478    * are loaded by the bootstrap class loader.
479    * </p>
480    * <p>
481    * When ignoring a type, any subsequently chained matcher is applied after this matcher in the order of their registration. Also, if
482    * any matcher indicates that a type is to be ignored, none of the following chained matchers is executed.
483    * </p>
484    * <p>
485    * <b>Note</b>: For performance reasons, it is recommended to always include a matcher that excludes as many namespaces
486    * as possible. Byte Buddy can determine a type's name without parsing its class file and can therefore discard such
487    * types with minimal overhead. When a different property of a type - such as for example its modifiers or its annotations
488    * is accessed - Byte Buddy parses the class file lazily in order to allow for such a matching. Therefore, any exclusion
489    * of a name should always be done as a first step and even if it does not influence the selection of what types are
490    * matched. Without changing this property, the class file of every type is being parsed!
491    * </p>
492    * <p>
493    * <b>Warning</b>: If a type is loaded during the instrumentation of the same type, this causes the original call site that loads the type
494    * to remain unbound, causing a {@link LinkageError}. It is therefore important to not instrument types that may be loaded during the application
495    * of a {@link Transformer}. For this reason, it is not recommended to instrument classes of the bootstrap class loader that Byte Buddy might
496    * require for instrumenting a class or to instrument any of Byte Buddy's classes. If such instrumentation is desired, it is important to
497    * assert for each class that they are not loaded during instrumentation.
498    * </p>
499    *
500    * @param typeMatcher A matcher that identifies types that should not be instrumented.
501    * @param classLoaderMatcher A matcher that identifies a class loader that identifies classes that should not be instrumented.
502    * @param moduleMatcher A matcher that identifies a module that identifies classes that should not be instrumented. On a JVM
503    * that does not support the Java modules system, this matcher is not applied.
504    * @return A new instance of this agent builder that ignores all types that are matched by the provided matcher.
505    * All previous matchers for ignored types are discarded.
506    */
507    Ignored ignore(ElementMatcher<? super TypeDescription> typeMatcher,
508    ElementMatcher<? super ClassLoader> classLoaderMatcher,
509    ElementMatcher<? super JavaModule> moduleMatcher);
510   
511    /**
512    * <p>
513    * Excludes any type that is matched by the raw matcher provided to this method. By default, Byte Buddy does not
514    * instrument synthetic types, types within a {@code net.bytebuddy.*} package or types that are loaded by the bootstrap class loader.
515    * </p>
516    * <p>
517    * When ignoring a type, any subsequently chained matcher is applied after this matcher in the order of their registration. Also, if
518    * any matcher indicates that a type is to be ignored, none of the following chained matchers is executed.
519    * </p>
520    * <p>
521    * <b>Note</b>: For performance reasons, it is recommended to always include a matcher that excludes as many namespaces
522    * as possible. Byte Buddy can determine a type's name without parsing its class file and can therefore discard such
523    * types with minimal overhead. When a different property of a type - such as for example its modifiers or its annotations
524    * is accessed - Byte Buddy parses the class file lazily in order to allow for such a matching. Therefore, any exclusion
525    * of a name should always be done as a first step and even if it does not influence the selection of what types are
526    * matched. Without changing this property, the class file of every type is being parsed!
527    * </p>
528    * <p>
529    * <b>Warning</b>: If a type is loaded during the instrumentation of the same type, this causes the original call site that loads the type
530    * to remain unbound, causing a {@link LinkageError}. It is therefore important to not instrument types that may be loaded during the application
531    * of a {@link Transformer}. For this reason, it is not recommended to instrument classes of the bootstrap class loader that Byte Buddy might
532    * require for instrumenting a class or to instrument any of Byte Buddy's classes. If such instrumentation is desired, it is important to
533    * assert for each class that they are not loaded during instrumentation.
534    * </p>
535    *
536    * @param rawMatcher A raw matcher that identifies types that should not be instrumented.
537    * @return A new instance of this agent builder that ignores all types that are matched by the provided matcher.
538    * All previous matchers for ignored types are discarded.
539    */
540    Ignored ignore(RawMatcher rawMatcher);
541   
542    /**
543    * Creates a {@link java.lang.instrument.ClassFileTransformer} that implements the configuration of this
544    * agent builder.
545    *
546    * @return A class file transformer that implements the configuration of this agent builder.
547    */
548    ClassFileTransformer makeRaw();
549   
550    /**
551    * <p>
552    * Creates and installs a {@link java.lang.instrument.ClassFileTransformer} that implements the configuration of
553    * this agent builder with a given {@link java.lang.instrument.Instrumentation}. If retransformation is enabled,
554    * the installation also causes all loaded types to be retransformed.
555    * </p>
556    * <p>
557    * If installing the created class file transformer causes an exception to be thrown, the consequences of this
558    * exception are determined by the {@link InstallationStrategy} of this builder.
559    * </p>
560    *
561    * @param instrumentation The instrumentation on which this agent builder's configuration is to be installed.
562    * @return The installed class file transformer.
563    */
564    ClassFileTransformer installOn(Instrumentation instrumentation);
565   
566    /**
567    * Creates and installs a {@link java.lang.instrument.ClassFileTransformer} that implements the configuration of
568    * this agent builder with the Byte Buddy-agent which must be installed prior to calling this method.
569    *
570    * @return The installed class file transformer.
571    * @see AgentBuilder#installOn(Instrumentation)
572    */
573    ClassFileTransformer installOnByteBuddyAgent();
574   
575    /**
576    * An abstraction for extending a matcher.
577    *
578    * @param <T> The type that is produced by chaining a matcher.
579    */
 
580    interface Matchable<T extends Matchable<T>> {
581   
582    /**
583    * Defines a matching that is positive if both the previous matcher and the supplied matcher are matched. When matching a
584    * type, class loaders are not considered.
585    *
586    * @param typeMatcher A matcher for the type being matched.
587    * @return A chained matcher.
588    */
589    T and(ElementMatcher<? super TypeDescription> typeMatcher);
590   
591    /**
592    * Defines a matching that is positive if both the previous matcher and the supplied matcher are matched.
593    *
594    * @param typeMatcher A matcher for the type being matched.
595    * @param classLoaderMatcher A matcher for the type's class loader.
596    * @return A chained matcher.
597    */
598    T and(ElementMatcher<? super TypeDescription> typeMatcher, ElementMatcher<? super ClassLoader> classLoaderMatcher);
599   
600    /**
601    * Defines a matching that is positive if both the previous matcher and the supplied matcher are matched.
602    *
603    * @param typeMatcher A matcher for the type being matched.
604    * @param classLoaderMatcher A matcher for the type's class loader.
605    * @param moduleMatcher A matcher for the type's module. On a JVM that does not support modules, the Java module is represented by {@code null}.
606    * @return A chained matcher.
607    */
608    T and(ElementMatcher<? super TypeDescription> typeMatcher,
609    ElementMatcher<? super ClassLoader> classLoaderMatcher,
610    ElementMatcher<? super JavaModule> moduleMatcher);
611   
612    /**
613    * Defines a matching that is positive if both the previous matcher and the supplied matcher are matched.
614    *
615    * @param rawMatcher A raw matcher for the type being matched.
616    * @return A chained matcher.
617    */
618    T and(RawMatcher rawMatcher);
619   
620    /**
621    * Defines a matching that is positive if the previous matcher or the supplied matcher are matched. When matching a
622    * type, the class loader is not considered.
623    *
624    * @param typeMatcher A matcher for the type being matched.
625    * @return A chained matcher.
626    */
627    T or(ElementMatcher<? super TypeDescription> typeMatcher);
628   
629    /**
630    * Defines a matching that is positive if the previous matcher or the supplied matcher are matched.
631    *
632    * @param typeMatcher A matcher for the type being matched.
633    * @param classLoaderMatcher A matcher for the type's class loader.
634    * @return A chained matcher.
635    */
636    T or(ElementMatcher<? super TypeDescription> typeMatcher, ElementMatcher<? super ClassLoader> classLoaderMatcher);
637   
638    /**
639    * Defines a matching that is positive if the previous matcher or the supplied matcher are matched.
640    *
641    * @param typeMatcher A matcher for the type being matched.
642    * @param classLoaderMatcher A matcher for the type's class loader.
643    * @param moduleMatcher A matcher for the type's module. On a JVM that does not support modules, the Java module is represented by {@code null}.
644    * @return A chained matcher.
645    */
646    T or(ElementMatcher<? super TypeDescription> typeMatcher,
647    ElementMatcher<? super ClassLoader> classLoaderMatcher,
648    ElementMatcher<? super JavaModule> moduleMatcher);
649   
650    /**
651    * Defines a matching that is positive if the previous matcher or the supplied matcher are matched.
652    *
653    * @param rawMatcher A raw matcher for the type being matched.
654    * @return A chained matcher.
655    */
656    T or(RawMatcher rawMatcher);
657   
658    /**
659    * An abstract base implementation of a matchable.
660    *
661    * @param <S> The type that is produced by chaining a matcher.
662    */
 
663    abstract class AbstractBase<S extends Matchable<S>> implements Matchable<S> {
664   
 
665  1 toggle @Override
666    public S and(ElementMatcher<? super TypeDescription> typeMatcher) {
667  1 return and(typeMatcher, any());
668    }
669   
 
670  1 toggle @Override
671    public S and(ElementMatcher<? super TypeDescription> typeMatcher, ElementMatcher<? super ClassLoader> classLoaderMatcher) {
672  1 return and(typeMatcher, classLoaderMatcher, any());
673    }
674   
 
675  1 toggle @Override
676    public S and(ElementMatcher<? super TypeDescription> typeMatcher,
677    ElementMatcher<? super ClassLoader> classLoaderMatcher,
678    ElementMatcher<? super JavaModule> moduleMatcher) {
679  1 return and(new RawMatcher.ForElementMatchers(typeMatcher, classLoaderMatcher, moduleMatcher));
680    }
681   
 
682  1 toggle @Override
683    public S or(ElementMatcher<? super TypeDescription> typeMatcher) {
684  1 return or(typeMatcher, any());
685    }
686   
 
687  1 toggle @Override
688    public S or(ElementMatcher<? super TypeDescription> typeMatcher, ElementMatcher<? super ClassLoader> classLoaderMatcher) {
689  1 return or(typeMatcher, classLoaderMatcher, any());
690    }
691   
 
692  1 toggle @Override
693    public S or(ElementMatcher<? super TypeDescription> typeMatcher,
694    ElementMatcher<? super ClassLoader> classLoaderMatcher,
695    ElementMatcher<? super JavaModule> moduleMatcher) {
696  1 return or(new RawMatcher.ForElementMatchers(typeMatcher, classLoaderMatcher, moduleMatcher));
697    }
698    }
699    }
700   
701    /**
702    * Allows to further specify ignored types.
703    */
 
704    interface Ignored extends Matchable<Ignored>, AgentBuilder {
705    /* this is merely a unionizing interface that does not declare methods */
706    }
707   
708    /**
709    * Describes an {@link net.bytebuddy.agent.builder.AgentBuilder} which was handed a matcher for identifying
710    * types to instrumented in order to supply one or several
711    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s.
712    */
 
713    interface Identified {
714   
715    /**
716    * Applies the given transformer for the already supplied matcher.
717    *
718    * @param transformer The transformer to apply.
719    * @return A new instance of this agent builder with the transformer being applied when the previously supplied matcher
720    * identified a type for instrumentation which also allows for the registration of subsequent transformers.
721    */
722    Extendable transform(Transformer transformer);
723   
724    /**
725    * Allows to specify a type matcher for a type to instrument.
726    */
 
727    interface Narrowable extends Matchable<Narrowable>, Identified {
728    /* this is merely a unionizing interface that does not declare methods */
729    }
730   
731    /**
732    * This interface is used to allow for optionally providing several
733    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer} to applied when a matcher identifies a type
734    * to be instrumented. Any subsequent transformers are applied in the order they are registered.
735    */
 
736    interface Extendable extends AgentBuilder, Identified {
737   
738    /**
739    * <p>
740    * Applies the specified transformation as a decorative transformation. For a decorative transformation, the supplied
741    * transformer is prepended to any previous transformation that also matches the instrumented type, i.e. both transformations
742    * are supplied. This procedure is repeated until a transformer is reached that matches the instrumented type but is not
743    * defined as decorating after which no further transformations are considered. If all matching transformations are declared
744    * as decorating, all matching transformers are applied.
745    * </p>
746    * <p>
747    * <b>Note</b>: A decorating transformer is applied <b>after</b> previously registered transformers.
748    * </p>
749    *
750    * @return A new instance of this agent builder with the specified transformation being applied as a decorator.
751    */
752    AgentBuilder asDecorator();
753    }
754    }
755   
756    /**
757    * A matcher that allows to determine if a {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}
758    * should be applied during the execution of a {@link java.lang.instrument.ClassFileTransformer} that was
759    * generated by an {@link net.bytebuddy.agent.builder.AgentBuilder}.
760    */
 
761    interface RawMatcher {
762   
763    /**
764    * Decides if the given {@code typeDescription} should be instrumented with the entailed
765    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s.
766    *
767    * @param typeDescription A description of the type to be instrumented.
768    * @param classLoader The class loader of the instrumented type. Might be {@code null} if this class
769    * loader represents the bootstrap class loader.
770    * @param module The transformed type's module or {@code null} if the current VM does not support modules.
771    * @param classBeingRedefined The class being redefined which is only not {@code null} if a retransformation
772    * is applied.
773    * @param protectionDomain The protection domain of the type being transformed.
774    * @return {@code true} if the entailed {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s should
775    * be applied for the given {@code typeDescription}.
776    */
777    boolean matches(TypeDescription typeDescription,
778    ClassLoader classLoader,
779    JavaModule module,
780    Class<?> classBeingRedefined,
781    ProtectionDomain protectionDomain);
782   
783    /**
784    * A conjunction of two raw matchers.
785    */
 
786    class Conjunction implements RawMatcher {
787   
788    /**
789    * The left matcher which is applied first.
790    */
791    private final RawMatcher left;
792   
793    /**
794    * The right matcher which is applied second.
795    */
796    private final RawMatcher right;
797   
798    /**
799    * Creates a new conjunction of two raw matchers.
800    *
801    * @param left The left matcher which is applied first.
802    * @param right The right matcher which is applied second.
803    */
 
804  10 toggle protected Conjunction(RawMatcher left, RawMatcher right) {
805  10 this.left = left;
806  10 this.right = right;
807    }
808   
 
809  6 toggle @Override
810    public boolean matches(TypeDescription typeDescription,
811    ClassLoader classLoader,
812    JavaModule module,
813    Class<?> classBeingRedefined,
814    ProtectionDomain protectionDomain) {
815  6 return left.matches(typeDescription, classLoader, module, classBeingRedefined, protectionDomain)
816    && right.matches(typeDescription, classLoader, module, classBeingRedefined, protectionDomain);
817    }
818   
 
819  6 toggle @Override
820    public boolean equals(Object object) {
821  1 if (this == object) return true;
822  2 if (object == null || getClass() != object.getClass()) return false;
823  3 Conjunction that = (Conjunction) object;
824  3 return left.equals(that.left) && right.equals(that.right);
825    }
826   
 
827  4 toggle @Override
828    public int hashCode() {
829  4 int result = left.hashCode();
830  4 result = 31 * result + right.hashCode();
831  4 return result;
832    }
833   
 
834  4 toggle @Override
835    public String toString() {
836  4 return "AgentBuilder.RawMatcher.Conjunction{" +
837    "left=" + left +
838    ", right=" + right +
839    '}';
840    }
841    }
842   
843    /**
844    * A disjunction of two raw matchers.
845    */
 
846    class Disjunction implements RawMatcher {
847   
848    /**
849    * The left matcher which is applied first.
850    */
851    private final RawMatcher left;
852   
853    /**
854    * The right matcher which is applied second.
855    */
856    private final RawMatcher right;
857   
858    /**
859    * Creates a new disjunction of two raw matchers.
860    *
861    * @param left The left matcher which is applied first.
862    * @param right The right matcher which is applied second.
863    */
 
864  167 toggle protected Disjunction(RawMatcher left, RawMatcher right) {
865  167 this.left = left;
866  167 this.right = right;
867    }
868   
 
869  7 toggle @Override
870    public boolean matches(TypeDescription typeDescription,
871    ClassLoader classLoader,
872    JavaModule module,
873    Class<?> classBeingRedefined,
874    ProtectionDomain protectionDomain) {
875  7 return left.matches(typeDescription, classLoader, module, classBeingRedefined, protectionDomain)
876    || right.matches(typeDescription, classLoader, module, classBeingRedefined, protectionDomain);
877    }
878   
 
879  9 toggle @Override
880    public boolean equals(Object object) {
881  1 if (this == object) return true;
882  2 if (object == null || getClass() != object.getClass()) return false;
883  6 Disjunction that = (Disjunction) object;
884  6 return left.equals(that.left) && right.equals(that.right);
885    }
886   
 
887  9 toggle @Override
888    public int hashCode() {
889  9 int result = left.hashCode();
890  9 result = 31 * result + right.hashCode();
891  9 return result;
892    }
893   
 
894  36 toggle @Override
895    public String toString() {
896  36 return "AgentBuilder.RawMatcher.Disjunction{" +
897    "left=" + left +
898    ", right=" + right +
899    '}';
900    }
901    }
902   
903    /**
904    * A raw matcher implementation that checks a {@link TypeDescription}
905    * and its {@link java.lang.ClassLoader} against two suitable matchers in order to determine if the matched
906    * type should be instrumented.
907    */
 
908    class ForElementMatchers implements RawMatcher {
909   
910    /**
911    * The type matcher to apply to a {@link TypeDescription}.
912    */
913    private final ElementMatcher<? super TypeDescription> typeMatcher;
914   
915    /**
916    * The class loader matcher to apply to a {@link java.lang.ClassLoader}.
917    */
918    private final ElementMatcher<? super ClassLoader> classLoaderMatcher;
919   
920    /**
921    * A module matcher to apply to a {@code java.lang.reflect.Module}.
922    */
923    private final ElementMatcher<? super JavaModule> moduleMatcher;
924   
925    /**
926    * Creates a new {@link net.bytebuddy.agent.builder.AgentBuilder.RawMatcher} that only matches the
927    * supplied {@link TypeDescription} and its {@link java.lang.ClassLoader} against two matcher in order
928    * to decided if an instrumentation should be conducted.
929    *
930    * @param typeMatcher The type matcher to apply to a {@link TypeDescription}.
931    * @param classLoaderMatcher The class loader matcher to apply to a {@link java.lang.ClassLoader}.
932    * @param moduleMatcher A module matcher to apply to a {@code java.lang.reflect.Module}.
933    */
 
934  579 toggle public ForElementMatchers(ElementMatcher<? super TypeDescription> typeMatcher,
935    ElementMatcher<? super ClassLoader> classLoaderMatcher,
936    ElementMatcher<? super JavaModule> moduleMatcher) {
937  579 this.typeMatcher = typeMatcher;
938  579 this.classLoaderMatcher = classLoaderMatcher;
939  579 this.moduleMatcher = moduleMatcher;
940    }
941   
 
942  261161 toggle @Override
943    public boolean matches(TypeDescription typeDescription,
944    ClassLoader classLoader,
945    JavaModule module,
946    Class<?> classBeingRedefined,
947    ProtectionDomain protectionDomain) {
948  261161 return moduleMatcher.matches(module) && classLoaderMatcher.matches(classLoader) && typeMatcher.matches(typeDescription);
949    }
950   
 
951  13 toggle @Override
952    public boolean equals(Object other) {
953  13 return this == other || !(other == null || getClass() != other.getClass())
954    && classLoaderMatcher.equals(((ForElementMatchers) other).classLoaderMatcher)
955    && moduleMatcher.equals(((ForElementMatchers) other).moduleMatcher)
956    && typeMatcher.equals(((ForElementMatchers) other).typeMatcher);
957    }
958   
 
959  143 toggle @Override
960    public int hashCode() {
961  143 int result = typeMatcher.hashCode();
962  143 result = 31 * result + classLoaderMatcher.hashCode();
963  143 result = 31 * result + moduleMatcher.hashCode();
964  143 return result;
965    }
966   
 
967  69 toggle @Override
968    public String toString() {
969  69 return "AgentBuilder.RawMatcher.ForElementMatchers{" +
970    "typeMatcher=" + typeMatcher +
971    ", classLoaderMatcher=" + classLoaderMatcher +
972    ", moduleMatcher=" + moduleMatcher +
973    '}';
974    }
975    }
976    }
977   
978    /**
979    * A type strategy is responsible for creating a type builder for a type that is being instrumented.
980    */
 
981    interface TypeStrategy {
982   
983    /**
984    * Creates a type builder for a given type.
985    *
986    * @param typeDescription The type being instrumented.
987    * @param byteBuddy The Byte Buddy configuration.
988    * @param classFileLocator The class file locator to use.
989    * @param methodNameTransformer The method name transformer to use.
990    * @return A type builder for the given arguments.
991    */
992    DynamicType.Builder<?> builder(TypeDescription typeDescription,
993    ByteBuddy byteBuddy,
994    ClassFileLocator classFileLocator,
995    MethodNameTransformer methodNameTransformer);
996   
997    /**
998    * Default implementations of type strategies.
999    */
 
1000    enum Default implements TypeStrategy {
1001   
1002    /**
1003    * A definition handler that performs a rebasing for all types.
1004    */
1005    REBASE {
 
1006  73 toggle @Override
1007    public DynamicType.Builder<?> builder(TypeDescription typeDescription,
1008    ByteBuddy byteBuddy,
1009    ClassFileLocator classFileLocator,
1010    MethodNameTransformer methodNameTransformer) {
1011  73 return byteBuddy.rebase(typeDescription, classFileLocator, methodNameTransformer);
1012    }
1013    },
1014   
1015    /**
1016    * <p>
1017    * A definition handler that performs a redefinition for all types.
1018    * </p>
1019    * <p>
1020    * Note that the default agent builder is configured to apply a self initialization where a static class initializer
1021    * is added to the redefined class. This can be disabled by for example using a {@link InitializationStrategy.Minimal} or
1022    * {@link InitializationStrategy.NoOp}. Also, consider the constraints implied by {@link ByteBuddy#redefine(TypeDescription, ClassFileLocator)}.
1023    * </p>
1024    * <p>
1025    * For prohibiting any changes on a class file, use {@link AgentBuilder#disableClassFormatChanges()}
1026    * </p>
1027    */
1028    REDEFINE {
 
1029  25 toggle @Override
1030    public DynamicType.Builder<?> builder(TypeDescription typeDescription,
1031    ByteBuddy byteBuddy,
1032    ClassFileLocator classFileLocator,
1033    MethodNameTransformer methodNameTransformer) {
1034  25 return byteBuddy.redefine(typeDescription, classFileLocator);
1035    }
1036    },
1037   
1038    /**
1039    * <p>
1040    * A definition handler that performs a redefinition for all types and ignores all methods that were not declared by the instrumented type.
1041    * </p>
1042    * <p>
1043    * Note that the default agent builder is configured to apply a self initialization where a static class initializer
1044    * is added to the redefined class. This can be disabled by for example using a {@link InitializationStrategy.Minimal} or
1045    * {@link InitializationStrategy.NoOp}. Also, consider the constraints implied by {@link ByteBuddy#redefine(TypeDescription, ClassFileLocator)}.
1046    * </p>
1047    * <p>
1048    * For prohibiting any changes on a class file, use {@link AgentBuilder#disableClassFormatChanges()}
1049    * </p>
1050    */
1051    REDEFINE_DECLARED_ONLY {
 
1052  1 toggle @Override
1053    public DynamicType.Builder<?> builder(TypeDescription typeDescription,
1054    ByteBuddy byteBuddy,
1055    ClassFileLocator classFileLocator,
1056    MethodNameTransformer methodNameTransformer) {
1057  1 return byteBuddy.redefine(typeDescription, classFileLocator).ignoreAlso(not(isDeclaredBy(typeDescription)));
1058    }
1059    };
1060   
 
1061  35 toggle @Override
1062    public String toString() {
1063  35 return "AgentBuilder.TypeStrategy.Default." + name();
1064    }
1065    }
1066    }
1067   
1068    /**
1069    * A transformer allows to apply modifications to a {@link net.bytebuddy.dynamic.DynamicType}. Such a modification
1070    * is then applied to any instrumented type that was matched by the preceding matcher.
1071    */
 
1072    interface Transformer {
1073   
1074    /**
1075    * Allows for a transformation of a {@link net.bytebuddy.dynamic.DynamicType.Builder}.
1076    *
1077    * @param builder The dynamic builder to transform.
1078    * @param typeDescription The description of the type currently being instrumented.
1079    * @param classLoader The class loader of the instrumented class. Might be {@code null} to
1080    * represent the bootstrap class loader.
1081    * @return A transformed version of the supplied {@code builder}.
1082    */
1083    DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader);
1084   
1085    /**
1086    * A no-op implementation of a {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer} that does
1087    * not modify the supplied dynamic type.
1088    */
 
1089    enum NoOp implements Transformer {
1090   
1091    /**
1092    * The singleton instance.
1093    */
1094    INSTANCE;
1095   
 
1096  112 toggle @Override
1097    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader) {
1098  112 return builder;
1099    }
1100   
 
1101  1 toggle @Override
1102    public String toString() {
1103  1 return "AgentBuilder.Transformer.NoOp." + name();
1104    }
1105    }
1106   
1107    /**
1108    * A compound transformer that allows to group several
1109    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s as a single transformer.
1110    */
 
1111    class Compound implements Transformer {
1112   
1113    /**
1114    * The transformers to apply in their application order.
1115    */
1116    private final Transformer[] transformer;
1117   
1118    /**
1119    * Creates a new compound transformer.
1120    *
1121    * @param transformer The transformers to apply in their application order.
1122    */
 
1123  151 toggle public Compound(Transformer... transformer) {
1124  151 this.transformer = transformer;
1125    }
1126   
 
1127  121 toggle @Override
1128    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader) {
1129  121 for (Transformer transformer : this.transformer) {
1130  242 builder = transformer.transform(builder, typeDescription, classLoader);
1131    }
1132  121 return builder;
1133    }
1134   
 
1135  5 toggle @Override
1136    public boolean equals(Object other) {
1137  5 return this == other || !(other == null || getClass() != other.getClass())
1138    && Arrays.equals(transformer, ((Compound) other).transformer);
1139    }
1140   
 
1141  59 toggle @Override
1142    public int hashCode() {
1143  59 return Arrays.hashCode(transformer);
1144    }
1145   
 
1146  3 toggle @Override
1147    public String toString() {
1148  3 return "AgentBuilder.Transformer.Compound{" +
1149    "transformer=" + Arrays.toString(transformer) +
1150    '}';
1151    }
1152    }
1153    }
1154   
1155    /**
1156    * A type locator allows to specify how {@link TypeDescription}s are resolved by an {@link net.bytebuddy.agent.builder.AgentBuilder}.
1157    */
 
1158    interface TypeLocator {
1159   
1160    /**
1161    * Creates a type pool for a given class file locator.
1162    *
1163    * @param classFileLocator The class file locator to use.
1164    * @param classLoader The class loader for which the class file locator was created.
1165    * @return A type pool for the supplied class file locator.
1166    */
1167    TypePool typePool(ClassFileLocator classFileLocator, ClassLoader classLoader);
1168   
1169    /**
1170    * A default implementation of a {@link TypeLocator} that is using a {@link net.bytebuddy.pool.TypePool.Default} with a
1171    * {@link net.bytebuddy.pool.TypePool.CacheProvider.Simple} and a {@link net.bytebuddy.dynamic.ClassFileLocator.ForClassLoader}.
1172    */
 
1173    enum Default implements TypeLocator {
1174   
1175    /**
1176    * A type locator that parses the code segment of each method for extracting information about parameter
1177    * names even if they are not explicitly included in a class file.
1178    *
1179    * @see net.bytebuddy.pool.TypePool.Default.ReaderMode#EXTENDED
1180    */
1181    EXTENDED(TypePool.Default.ReaderMode.EXTENDED),
1182   
1183    /**
1184    * A type locator that skips the code segment of each method and does therefore not extract information
1185    * about parameter names. Parameter names are still included if they are explicitly included in a class file.
1186    *
1187    * @see net.bytebuddy.pool.TypePool.Default.ReaderMode#FAST
1188    */
1189    FAST(TypePool.Default.ReaderMode.FAST);
1190   
1191    /**
1192    * The reader mode to apply by this type locator.
1193    */
1194    private final TypePool.Default.ReaderMode readerMode;
1195   
1196    /**
1197    * Creates a new type locator.
1198    *
1199    * @param readerMode The reader mode to apply by this type locator.
1200    */
 
1201  2 toggle Default(TypePool.Default.ReaderMode readerMode) {
1202  2 this.readerMode = readerMode;
1203    }
1204   
 
1205  23776 toggle @Override
1206    public TypePool typePool(ClassFileLocator classFileLocator, ClassLoader classLoader) {
1207  23776 return new TypePool.LazyFacade(new TypePool.Default(TypePool.CacheProvider.Simple.withObjectType(), classFileLocator, readerMode));
1208    }
1209   
 
1210  34 toggle @Override
1211    public String toString() {
1212  34 return "AgentBuilder.TypeLocator.Default." + name();
1213    }
1214    }
1215   
1216    /**
1217    * An implementation of a {@link TypeLocator} that is using a {@link net.bytebuddy.pool.TypePool.Default} with a
1218    * {@link net.bytebuddy.pool.TypePool.CacheProvider.Simple} and a {@link net.bytebuddy.dynamic.ClassFileLocator.ForClassLoader}.
1219    * Additionally, this type locator falls back to class loadings for non-locatable class files.
1220    */
 
1221    enum ClassLoading implements TypeLocator {
1222   
1223    /**
1224    * A type locator that parses the code segment of each method for extracting information about parameter
1225    * names even if they are not explicitly included in a class file.
1226    *
1227    * @see net.bytebuddy.pool.TypePool.Default.ReaderMode#EXTENDED
1228    */
1229    EXTENDED(TypePool.Default.ReaderMode.EXTENDED),
1230   
1231    /**
1232    * A type locator that skips the code segment of each method and does therefore not extract information
1233    * about parameter names. Parameter names are still included if they are explicitly included in a class file.
1234    *
1235    * @see net.bytebuddy.pool.TypePool.Default.ReaderMode#FAST
1236    */
1237    FAST(TypePool.Default.ReaderMode.FAST);
1238   
1239    /**
1240    * The reader mode to apply by this type locator.
1241    */
1242    private final TypePool.Default.ReaderMode readerMode;
1243   
1244    /**
1245    * Creates a new type locator.
1246    *
1247    * @param readerMode The reader mode to apply by this type locator.
1248    */
 
1249  2 toggle ClassLoading(TypePool.Default.ReaderMode readerMode) {
1250  2 this.readerMode = readerMode;
1251    }
1252   
 
1253  24353 toggle @Override
1254    public TypePool typePool(ClassFileLocator classFileLocator, ClassLoader classLoader) {
1255  24353 return new TypePool.LazyFacade(TypePool.ClassLoading.of(classLoader, new TypePool.Default(TypePool.CacheProvider.Simple.withObjectType(), classFileLocator, readerMode)));
1256    }
1257   
 
1258  2 toggle @Override
1259    public String toString() {
1260  2 return "AgentBuilder.TypeLocator.ClassLoading." + name();
1261    }
1262    }
1263   
1264    /**
1265    * A type locator that uses type pools but allows for the configuration of a custom cache provider by class loader. Note that a
1266    * {@link TypePool} can grow in size and that a static reference is kept to this pool by Byte Buddy's registration of a
1267    * {@link ClassFileTransformer} what can cause a memory leak if the supplied caches are not cleared on a regular basis. Also note
1268    * that a cache provider can be accessed concurrently by multiple {@link ClassLoader}s.
1269    */
 
1270    abstract class WithTypePoolCache implements TypeLocator {
1271   
1272    /**
1273    * The reader mode to use for parsing a class file.
1274    */
1275    protected final TypePool.Default.ReaderMode readerMode;
1276   
1277    /**
1278    * Creates a new type locator that creates {@link TypePool}s but provides a custom {@link net.bytebuddy.pool.TypePool.CacheProvider}.
1279    *
1280    * @param readerMode The reader mode to use for parsing a class file.
1281    */
 
1282  9 toggle protected WithTypePoolCache(TypePool.Default.ReaderMode readerMode) {
1283  9 this.readerMode = readerMode;
1284    }
1285   
 
1286  8 toggle @Override
1287    public TypePool typePool(ClassFileLocator classFileLocator, ClassLoader classLoader) {
1288  8 return new TypePool.LazyFacade(new TypePool.Default(locate(classLoader), classFileLocator, readerMode));
1289    }
1290   
1291    /**
1292    * Locates a cache provider for a given class loader.
1293    *
1294    * @param classLoader The class loader for which to locate a cache. This class loader might be {@code null} to represent the bootstrap loader.
1295    * @return The cache provider to use.
1296    */
1297    protected abstract TypePool.CacheProvider locate(ClassLoader classLoader);
1298   
 
1299  5 toggle @Override
1300    public boolean equals(Object object) {
1301  5 if (this == object) return true;
1302  5 if (object == null || getClass() != object.getClass()) return false;
1303  5 WithTypePoolCache that = (WithTypePoolCache) object;
1304  5 return readerMode == that.readerMode;
1305    }
1306   
 
1307  7 toggle @Override
1308    public int hashCode() {
1309  7 return readerMode.hashCode();
1310    }
1311   
1312    /**
1313    * An implementation of a type locator {@link WithTypePoolCache} (note documentation of the linked class) that is based on a
1314    * {@link ConcurrentMap}. It is the responsibility of the type locator's user to avoid the type locator from leaking memory.
1315    */
 
1316    public static class Simple extends WithTypePoolCache {
1317   
1318    /**
1319    * The concurrent map that is used for storing a cache provider per class loader.
1320    */
1321    private final ConcurrentMap<? super ClassLoader, TypePool.CacheProvider> cacheProviders;
1322   
1323    /**
1324    * Creates a new type locator that caches a cache provider per class loader in a concurrent map. The type
1325    * locator uses a fast {@link net.bytebuddy.pool.TypePool.Default.ReaderMode}.
1326    *
1327    * @param cacheProviders The concurrent map that is used for storing a cache provider per class loader.
1328    */
 
1329  3 toggle public Simple(ConcurrentMap<? super ClassLoader, TypePool.CacheProvider> cacheProviders) {
1330  3 this(TypePool.Default.ReaderMode.FAST, cacheProviders);
1331    }
1332   
1333    /**
1334    * Creates a new type locator that caches a cache provider per class loader in a concurrent map.
1335    *
1336    * @param readerMode The reader mode to use for parsing a class file.
1337    * @param cacheProviders The concurrent map that is used for storing a cache provider per class loader.
1338    */
 
1339  9 toggle public Simple(TypePool.Default.ReaderMode readerMode, ConcurrentMap<? super ClassLoader, TypePool.CacheProvider> cacheProviders) {
1340  9 super(readerMode);
1341  9 this.cacheProviders = cacheProviders;
1342    }
1343   
 
1344  8 toggle @Override
1345    protected TypePool.CacheProvider locate(ClassLoader classLoader) {
1346  8 classLoader = classLoader == null ? BootstrapClassLoaderMarker.INSTANCE : classLoader;
1347  8 TypePool.CacheProvider cacheProvider = cacheProviders.get(classLoader);
1348  12 while (cacheProvider == null) {
1349  4 cacheProviders.putIfAbsent(classLoader, TypePool.CacheProvider.Simple.withObjectType());
1350  4 cacheProvider = cacheProviders.get(classLoader);
1351    }
1352  8 return cacheProvider;
1353    }
1354   
 
1355  11 toggle @Override
1356    public boolean equals(Object object) {
1357  2 if (this == object) return true;
1358  4 if (object == null || getClass() != object.getClass()) return false;
1359  1 if (!super.equals(object)) return false;
1360  4 Simple simple = (Simple) object;
1361  4 return cacheProviders.equals(simple.cacheProviders);
1362    }
1363   
 
1364  7 toggle @Override
1365    public int hashCode() {
1366  7 int result = super.hashCode();
1367  7 result = 31 * result + cacheProviders.hashCode();
1368  7 return result;
1369    }
1370   
 
1371  8 toggle @Override
1372    public String toString() {
1373  8 return "AgentBuilder.TypeLocator.WithTypePoolCache.Simple{" +
1374    "cacheProviders=" + cacheProviders +
1375    '}';
1376    }
1377   
1378    /**
1379    * A marker for the bootstrap class loader which is represented by {@code null}.
1380    */
 
1381    private static class BootstrapClassLoaderMarker extends ClassLoader {
1382   
1383    /**
1384    * A static reference to the a singleton instance of the marker to preserve reference equality.
1385    */
1386    protected static final ClassLoader INSTANCE = AccessController.doPrivileged(new CreationAction());
1387   
 
1388  0 toggle @Override
1389    protected Class<?> loadClass(String name, boolean resolve) {
1390  0 throw new UnsupportedOperationException("This loader is only a non-null marker and is not supposed to be used");
1391    }
1392   
1393    /**
1394    * A simple action for creating a bootstrap class loader marker.
1395    */
 
1396    private static class CreationAction implements PrivilegedAction<ClassLoader> {
1397   
 
1398  1 toggle @Override
1399    public ClassLoader run() {
1400  1 return new BootstrapClassLoaderMarker();
1401    }
1402    }
1403    }
1404    }
1405    }
1406    }
1407   
1408    /**
1409    * A listener that is informed about events that occur during an instrumentation process.
1410    */
 
1411    interface Listener {
1412   
1413    /**
1414    * Invoked right before a successful transformation is applied.
1415    *
1416    * @param typeDescription The type that is being transformed.
1417    * @param classLoader The class loader which is loading this type.
1418    * @param module The transformed type's module or {@code null} if the current VM does not support modules.
1419    * @param dynamicType The dynamic type that was created.
1420    */
1421    void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, DynamicType dynamicType);
1422   
1423    /**
1424    * Invoked when a type is not transformed but ignored.
1425    *
1426    * @param typeDescription The type being ignored for transformation.
1427    * @param classLoader The class loader which is loading this type.
1428    * @param module The ignored type's module or {@code null} if the current VM does not support modules.
1429    */
1430    void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module);
1431   
1432    /**
1433    * Invoked when an error has occurred during transformation.
1434    *
1435    * @param typeName The type name of the instrumented type.
1436    * @param classLoader The class loader which is loading this type.
1437    * @param module The instrumented type's module or {@code null} if the current VM does not support modules.
1438    * @param throwable The occurred error.
1439    */
1440    void onError(String typeName, ClassLoader classLoader, JavaModule module, Throwable throwable);
1441   
1442    /**
1443    * Invoked after a class was attempted to be loaded, independently of its treatment.
1444    *
1445    * @param typeName The binary name of the instrumented type.
1446    * @param classLoader The class loader which is loading this type.
1447    * @param module The instrumented type's module or {@code null} if the current VM does not support modules.
1448    */
1449    void onComplete(String typeName, ClassLoader classLoader, JavaModule module);
1450   
1451    /**
1452    * A no-op implementation of a {@link net.bytebuddy.agent.builder.AgentBuilder.Listener}.
1453    */
 
1454    enum NoOp implements Listener {
1455   
1456    /**
1457    * The singleton instance.
1458    */
1459    INSTANCE;
1460   
 
1461  103 toggle @Override
1462    public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, DynamicType dynamicType) {
1463    /* do nothing */
1464    }
1465   
 
1466  239258 toggle @Override
1467    public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
1468    /* do nothing */
1469    }
1470   
 
1471  6 toggle @Override
1472    public void onError(String typeName, ClassLoader classLoader, JavaModule module, Throwable throwable) {
1473    /* do nothing */
1474    }
1475   
 
1476  239365 toggle @Override
1477    public void onComplete(String typeName, ClassLoader classLoader, JavaModule module) {
1478    /* do nothing */
1479    }
1480   
 
1481  33 toggle @Override
1482    public String toString() {
1483  33 return "AgentBuilder.Listener.NoOp." + name();
1484    }
1485    }
1486   
1487    /**
1488    * An adapter for a listener wher all methods are implemented as non-operational.
1489    */
 
1490    abstract class Adapter implements Listener {
1491   
 
1492  1 toggle @Override
1493    public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, DynamicType dynamicType) {
1494    /* do nothing */
1495    }
1496   
 
1497  1 toggle @Override
1498    public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
1499    /* do nothing */
1500    }
1501   
 
1502  1 toggle @Override
1503    public void onError(String typeName, ClassLoader classLoader, JavaModule module, Throwable throwable) {
1504    /* do nothing */
1505    }
1506   
 
1507  1 toggle @Override
1508    public void onComplete(String typeName, ClassLoader classLoader, JavaModule module) {
1509    /* do nothing */
1510    }
1511    }
1512   
1513    /**
1514    * A listener that writes events to a {@link PrintStream}. This listener prints a line per event, including the event type and
1515    * the name of the type in question.
1516    */
 
1517    class StreamWriting implements Listener {
1518   
1519    /**
1520    * The prefix that is appended to all written messages.
1521    */
1522    protected static final String PREFIX = "[Byte Buddy]";
1523   
1524    /**
1525    * The print stream written to.
1526    */
1527    private final PrintStream printStream;
1528   
1529    /**
1530    * Creates a new stream writing listener.
1531    *
1532    * @param printStream The print stream written to.
1533    */
 
1534  11 toggle public StreamWriting(PrintStream printStream) {
1535  11 this.printStream = printStream;
1536    }
1537   
1538    /**
1539    * Creates a new stream writing listener that writes to {@link System#out}.
1540    *
1541    * @return A listener writing events to the standard output stream.
1542    */
 
1543  1 toggle public static Listener toSystemOut() {
1544  1 return new StreamWriting(System.out);
1545    }
1546   
1547    /**
1548    * Creates a new stream writing listener that writes to {@link System#err}.
1549    *
1550    * @return A listener writing events to the standad error stream.
1551    */
 
1552  1 toggle public static Listener toSystemError() {
1553  1 return new StreamWriting(System.err);
1554    }
1555   
 
1556  1 toggle @Override
1557    public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, DynamicType dynamicType) {
1558  1 printStream.println(PREFIX + " TRANSFORM " + typeDescription.getName() + "[" + classLoader + ", " + module + "]");
1559    }
1560   
 
1561  1 toggle @Override
1562    public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
1563  1 printStream.println(PREFIX + " IGNORE " + typeDescription.getName() + "[" + classLoader + ", " + module + "]");
1564    }
1565   
 
1566  1 toggle @Override
1567    public void onError(String typeName, ClassLoader classLoader, JavaModule module, Throwable throwable) {
1568  1 printStream.println(PREFIX + " ERROR " + typeName + "[" + classLoader + ", " + module + "]");
1569  1 throwable.printStackTrace(printStream);
1570    }
1571   
 
1572  1 toggle @Override
1573    public void onComplete(String typeName, ClassLoader classLoader, JavaModule module) {
1574  1 printStream.println(PREFIX + " COMPLETE " + typeName + "[" + classLoader + ", " + module + "]");
1575    }
1576   
 
1577  7 toggle @Override
1578    public boolean equals(Object other) {
1579  7 return this == other || !(other == null || getClass() != other.getClass())
1580    && printStream.equals(((StreamWriting) other).printStream);
1581    }
1582   
 
1583  3 toggle @Override
1584    public int hashCode() {
1585  3 return printStream.hashCode();
1586    }
1587   
 
1588  3 toggle @Override
1589    public String toString() {
1590  3 return "AgentBuilder.Listener.StreamWriting{" +
1591    "printStream=" + printStream +
1592    '}';
1593    }
1594    }
1595   
1596    /**
1597    * A listener that adds read-edges to any module of an instrumented class upon its transformation.
1598    */
 
1599    class ModuleReadEdgeCompleting extends Listener.Adapter {
1600   
1601    /**
1602    * The instrumentation instance used for adding read edges.
1603    */
1604    private final Instrumentation instrumentation;
1605   
1606    /**
1607    * {@code true} if the listener should also add a read-edge from the supplied modules to the instrumented type's module.
1608    */
1609    private final boolean addTargetEdge;
1610   
1611    /**
1612    * The modules to add as a read edge to any transformed class's module.
1613    */
1614    private final Set<? extends JavaModule> modules;
1615   
1616    /**
1617    * Creates a new module read-edge completing listener.
1618    *
1619    * @param instrumentation The instrumentation instance used for adding read edges.
1620    * @param addTargetEdge {@code true} if the listener should also add a read-edge from the supplied modules
1621    * to the instrumented type's module.
1622    * @param modules The modules to add as a read edge to any transformed class's module.
1623    */
 
1624  13 toggle public ModuleReadEdgeCompleting(Instrumentation instrumentation, boolean addTargetEdge, Set<? extends JavaModule> modules) {
1625  13 this.instrumentation = instrumentation;
1626  13 this.addTargetEdge = addTargetEdge;
1627  13 this.modules = modules;
1628    }
1629   
1630    /**
1631    * Resolves a listener that adds module edges from and to the instrumented type's module.
1632    *
1633    * @param instrumentation The instrumentation instance used for adding read edges.
1634    * @param addTargetEdge {@code true} if the listener should also add a read-edge from the supplied
1635    * modules to the instrumented type's module.
1636    * @param type The types for which to extract the modules.
1637    * @return An appropriate listener.
1638    */
 
1639  0 toggle protected static Listener of(Instrumentation instrumentation, boolean addTargetEdge, Class<?>... type) {
1640  0 Set<JavaModule> modules = new HashSet<JavaModule>();
1641  0 for (Class<?> aType : type) {
1642  0 JavaModule module = JavaModule.ofType(aType);
1643  0 if (module.isNamed()) {
1644  0 modules.add(module);
1645    }
1646    }
1647  0 return modules.isEmpty()
1648    ? Listener.NoOp.INSTANCE
1649    : new Listener.ModuleReadEdgeCompleting(instrumentation, addTargetEdge, modules);
1650    }
1651   
 
1652  8 toggle @Override
1653    public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, DynamicType dynamicType) {
1654  8 if (module != null && module.isNamed()) {
1655  4 for (JavaModule target : modules) {
1656  4 if (!module.canRead(target)) {
1657  2 module.addReads(instrumentation, target);
1658    }
1659  4 if (addTargetEdge && !target.canRead(module)) {
1660  1 target.addReads(instrumentation, module);
1661    }
1662    }
1663    }
1664    }
1665   
 
1666  7 toggle @Override
1667    public boolean equals(Object object) {
1668  1 if (this == object) return true;
1669  2 if (object == null || getClass() != object.getClass()) return false;
1670  4 ModuleReadEdgeCompleting that = (ModuleReadEdgeCompleting) object;
1671  4 return instrumentation.equals(that.instrumentation)
1672    && addTargetEdge == that.addTargetEdge
1673    && modules.equals(that.modules);
1674    }
1675   
 
1676  5 toggle @Override
1677    public int hashCode() {
1678  5 int result = instrumentation.hashCode();
1679  5 result = 31 * result + modules.hashCode();
1680  5 result = 31 * result + (addTargetEdge ? 1 : 0);
1681  5 return result;
1682    }
1683   
 
1684  8 toggle @Override
1685    public String toString() {
1686  8 return "AgentBuilder.Listener.ModuleReadEdgeCompleting{" +
1687    "instrumentation=" + instrumentation +
1688    ", addTargetEdge=" + addTargetEdge +
1689    ", modules=" + modules +
1690    '}';
1691    }
1692    }
1693   
1694    /**
1695    * A compound listener that allows to group several listeners in one instance.
1696    */
 
1697    class Compound implements Listener {
1698   
1699    /**
1700    * The listeners that are represented by this compound listener in their application order.
1701    */
1702    private final List<? extends Listener> listeners;
1703   
1704    /**
1705    * Creates a new compound listener.
1706    *
1707    * @param listener The listeners to apply in their application order.
1708    */
 
1709  39 toggle public Compound(Listener... listener) {
1710  39 this(Arrays.asList(listener));
1711    }
1712   
1713    /**
1714    * Creates a new compound listener.
1715    *
1716    * @param listeners The listeners to apply in their application order.
1717    */
 
1718  42 toggle public Compound(List<? extends Listener> listeners) {
1719  42 this.listeners = listeners;
1720    }
1721   
 
1722  7 toggle @Override
1723    public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, DynamicType dynamicType) {
1724  7 for (Listener listener : listeners) {
1725  14 listener.onTransformation(typeDescription, classLoader, module, dynamicType);
1726    }
1727    }
1728   
 
1729  14 toggle @Override
1730    public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
1731  14 for (Listener listener : listeners) {
1732  28 listener.onIgnored(typeDescription, classLoader, module);
1733    }
1734    }
1735   
 
1736  6 toggle @Override
1737    public void onError(String typeName, ClassLoader classLoader, JavaModule module, Throwable throwable) {
1738  6 for (Listener listener : listeners) {
1739  12 listener.onError(typeName, classLoader, module, throwable);
1740    }
1741    }
1742   
 
1743  25 toggle @Override
1744    public void onComplete(String typeName, ClassLoader classLoader, JavaModule module) {
1745  25 for (Listener listener : listeners) {
1746  50 listener.onComplete(typeName, classLoader, module);
1747    }
1748    }
1749   
 
1750  10 toggle @Override
1751    public boolean equals(Object other) {
1752  10 return this == other || !(other == null || getClass() != other.getClass())
1753    && listeners.equals(((Compound) other).listeners);
1754    }
1755   
 
1756  6 toggle @Override
1757    public int hashCode() {
1758  6 return listeners.hashCode();
1759    }
1760   
 
1761  6 toggle @Override
1762    public String toString() {
1763  6 return "AgentBuilder.Listener.Compound{" +
1764    "listeners=" + listeners +
1765    '}';
1766    }
1767    }
1768    }
1769   
1770    /**
1771    * An initialization strategy which determines the handling of {@link net.bytebuddy.implementation.LoadedTypeInitializer}s
1772    * and the loading of auxiliary types.
1773    */
 
1774    interface InitializationStrategy {
1775   
1776    /**
1777    * Creates a new dispatcher for injecting this initialization strategy during a transformation process.
1778    *
1779    * @return The dispatcher to be used.
1780    */
1781    Dispatcher dispatcher();
1782   
1783    /**
1784    * A dispatcher for changing a class file to adapt a self-initialization strategy.
1785    */
 
1786    interface Dispatcher {
1787   
1788    /**
1789    * Transforms the instrumented type to implement an appropriate initialization strategy.
1790    *
1791    * @param builder The builder which should implement the initialization strategy.
1792    * @return The given {@code builder} with the initialization strategy applied.
1793    */
1794    DynamicType.Builder<?> apply(DynamicType.Builder<?> builder);
1795   
1796    /**
1797    * Registers a dynamic type for initialization and/or begins the initialization process.
1798    *
1799    * @param dynamicType The dynamic type that is created.
1800    * @param classLoader The class loader of the dynamic type.
1801    * @param injectorFactory The injector factory
1802    */
1803    void register(DynamicType dynamicType, ClassLoader classLoader, InjectorFactory injectorFactory);
1804   
1805    /**
1806    * A factory for creating a {@link ClassInjector} only if it is required.
1807    */
 
1808    interface InjectorFactory {
1809   
1810    /**
1811    * Resolves the class injector for this factory.
1812    *
1813    * @return The class injector for this factory.
1814    */
1815    ClassInjector resolve();
1816    }
1817    }
1818   
1819    /**
1820    * A non-initializing initialization strategy.
1821    */
 
1822    enum NoOp implements InitializationStrategy, Dispatcher {
1823   
1824    /**
1825    * The singleton instance.
1826    */
1827    INSTANCE;
1828   
 
1829  33 toggle @Override
1830    public Dispatcher dispatcher() {
1831  33 return this;
1832    }
1833   
 
1834  33 toggle @Override
1835    public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder) {
1836  33 return builder;
1837    }
1838   
 
1839  33 toggle @Override
1840    public void register(DynamicType dynamicType, ClassLoader classLoader, InjectorFactory injectorFactory) {
1841    /* do nothing */
1842    }
1843   
 
1844  1 toggle @Override
1845    public String toString() {
1846  1 return "AgentBuilder.InitializationStrategy.NoOp." + name();
1847    }
1848    }
1849   
1850    /**
1851    * An initialization strategy that adds a code block to an instrumented type's type initializer which
1852    * then calls a specific class that is responsible for the explicit initialization.
1853    */
1854    @SuppressFBWarnings(value = "DMI_RANDOM_USED_ONLY_ONCE", justification = "Avoiding synchronization without security concerns")
 
1855    enum SelfInjection implements InitializationStrategy {
1856   
1857    /**
1858    * A form of self-injection where auxiliary types that are annotated by
1859    * {@link net.bytebuddy.implementation.auxiliary.AuxiliaryType.SignatureRelevant} of the instrumented type are loaded lazily and
1860    * any other auxiliary type is loaded eagerly.
1861    */
1862    SPLIT {
 
1863  65 toggle @Override
1864    public InitializationStrategy.Dispatcher dispatcher() {
1865  65 return new SelfInjection.Dispatcher.Split(new Random().nextInt());
1866    }
1867    },
1868   
1869    /**
1870    * A form of self-injection where any auxiliary type is loaded lazily.
1871    */
1872    LAZY {
 
1873  1 toggle @Override
1874    public InitializationStrategy.Dispatcher dispatcher() {
1875  1 return new SelfInjection.Dispatcher.Lazy(new Random().nextInt());
1876    }
1877    },
1878   
1879    /**
1880    * A form of self-injection where any auxiliary type is loaded eagerly.
1881    */
1882    EAGER {
 
1883  1 toggle @Override
1884    public InitializationStrategy.Dispatcher dispatcher() {
1885  1 return new SelfInjection.Dispatcher.Eager(new Random().nextInt());
1886    }
1887    };
1888   
 
1889  35 toggle @Override
1890    public String toString() {
1891  35 return "AgentBuilder.InitializationStrategy.SelfInjection." + name();
1892    }
1893   
1894    /**
1895    * A dispatcher for a self-initialization strategy.
1896    */
 
1897    protected abstract static class Dispatcher implements InitializationStrategy.Dispatcher {
1898   
1899    /**
1900    * A random identification for the applied self-initialization.
1901    */
1902    protected final int identification;
1903   
1904    /**
1905    * Creates a new dispatcher.
1906    *
1907    * @param identification A random identification for the applied self-initialization.
1908    */
 
1909  82 toggle protected Dispatcher(int identification) {
1910  82 this.identification = identification;
1911    }
1912   
 
1913  67 toggle @Override
1914    public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder) {
1915  67 return builder.initializer(NexusAccessor.INSTANCE.identifiedBy(identification));
1916    }
1917   
 
1918  15 toggle @Override
1919    public boolean equals(Object other) {
1920  15 return this == other || !(other == null || getClass() != other.getClass())
1921    && identification == ((Dispatcher) other).identification;
1922    }
1923   
 
1924  9 toggle @Override
1925    public int hashCode() {
1926  9 return identification;
1927    }
1928   
1929    /**
1930    * A dispatcher for the {@link net.bytebuddy.agent.builder.AgentBuilder.InitializationStrategy.SelfInjection#SPLIT} strategy.
1931    */
 
1932    protected static class Split extends Dispatcher {
1933   
1934    /**
1935    * Creates a new split dispatcher.
1936    *
1937    * @param identification A random identification for the applied self-initialization.
1938    */
 
1939  70 toggle protected Split(int identification) {
1940  70 super(identification);
1941    }
1942   
 
1943  65 toggle @Override
1944    public void register(DynamicType dynamicType, ClassLoader classLoader, InjectorFactory injectorFactory) {
1945  65 Map<TypeDescription, byte[]> auxiliaryTypes = dynamicType.getAuxiliaryTypes();
1946  65 LoadedTypeInitializer loadedTypeInitializer;
1947  65 if (!auxiliaryTypes.isEmpty()) {
1948  21 TypeDescription instrumentedType = dynamicType.getTypeDescription();
1949  21 ClassInjector classInjector = injectorFactory.resolve();
1950  21 Map<TypeDescription, byte[]> independentTypes = new LinkedHashMap<TypeDescription, byte[]>(auxiliaryTypes);
1951  21 Map<TypeDescription, byte[]> dependentTypes = new LinkedHashMap<TypeDescription, byte[]>(auxiliaryTypes);
1952  21 for (TypeDescription auxiliaryType : auxiliaryTypes.keySet()) {
1953  22 (auxiliaryType.getDeclaredAnnotations().isAnnotationPresent(AuxiliaryType.SignatureRelevant.class)
1954    ? dependentTypes
1955    : independentTypes).remove(auxiliaryType);
1956    }
1957  21 Map<TypeDescription, LoadedTypeInitializer> loadedTypeInitializers = dynamicType.getLoadedTypeInitializers();
1958  5 if (!independentTypes.isEmpty()) {
1959  5 for (Map.Entry<TypeDescription, Class<?>> entry : classInjector.inject(independentTypes).entrySet()) {
1960  5 loadedTypeInitializers.get(entry.getKey()).onLoad(entry.getValue());
1961    }
1962    }
1963  21 Map<TypeDescription, LoadedTypeInitializer> lazyInitializers = new HashMap<TypeDescription, LoadedTypeInitializer>(loadedTypeInitializers);
1964  21 loadedTypeInitializers.keySet().removeAll(independentTypes.keySet());
1965  21 loadedTypeInitializer = lazyInitializers.size() > 1 // there exist auxiliary types that need lazy loading
1966    ? new InjectingInitializer(instrumentedType, dependentTypes, lazyInitializers, classInjector)
1967    : lazyInitializers.get(instrumentedType);
1968    } else {
1969  44 loadedTypeInitializer = dynamicType.getLoadedTypeInitializers().get(dynamicType.getTypeDescription());
1970    }
1971  65 if (loadedTypeInitializer.isAlive()) {
1972  25 NexusAccessor.INSTANCE.register(dynamicType.getTypeDescription().getName(), classLoader, identification, loadedTypeInitializer);
1973    }
1974    }
1975   
 
1976  2 toggle @Override
1977    public String toString() {
1978  2 return "AgentBuilder.InitializationStrategy.SelfInjection.Dispatcher.Split{identification=" + identification + "}";
1979    }
1980    }
1981   
1982    /**
1983    * A dispatcher for the {@link net.bytebuddy.agent.builder.AgentBuilder.InitializationStrategy.SelfInjection#LAZY} strategy.
1984    */
 
1985    protected static class Lazy extends Dispatcher {
1986   
1987    /**
1988    * Creates a new lazy dispatcher.
1989    *
1990    * @param identification A random identification for the applied self-initialization.
1991    */
 
1992  6 toggle protected Lazy(int identification) {
1993  6 super(identification);
1994    }
1995   
 
1996  1 toggle @Override
1997    public void register(DynamicType dynamicType, ClassLoader classLoader, InjectorFactory injectorFactory) {
1998  1 Map<TypeDescription, byte[]> auxiliaryTypes = dynamicType.getAuxiliaryTypes();
1999  1 LoadedTypeInitializer loadedTypeInitializer = auxiliaryTypes.isEmpty()
2000    ? dynamicType.getLoadedTypeInitializers().get(dynamicType.getTypeDescription())
2001    : new InjectingInitializer(dynamicType.getTypeDescription(), auxiliaryTypes, dynamicType.getLoadedTypeInitializers(), injectorFactory.resolve());
2002  1 if (loadedTypeInitializer.isAlive()) {
2003  1 NexusAccessor.INSTANCE.register(dynamicType.getTypeDescription().getName(), classLoader, identification, loadedTypeInitializer);
2004    }
2005    }
2006   
 
2007  2 toggle @Override
2008    public String toString() {
2009  2 return "AgentBuilder.InitializationStrategy.SelfInjection.Dispatcher.Lazy{identification=" + identification + "}";
2010    }
2011    }
2012   
2013    /**
2014    * A dispatcher for the {@link net.bytebuddy.agent.builder.AgentBuilder.InitializationStrategy.SelfInjection#EAGER} strategy.
2015    */
 
2016    protected static class Eager extends Dispatcher {
2017   
2018    /**
2019    * Creates a new eager dispatcher.
2020    *
2021    * @param identification A random identification for the applied self-initialization.
2022    */
 
2023  6 toggle protected Eager(int identification) {
2024  6 super(identification);
2025    }
2026   
 
2027  1 toggle @Override
2028    public void register(DynamicType dynamicType, ClassLoader classLoader, InjectorFactory injectorFactory) {
2029  1 Map<TypeDescription, byte[]> auxiliaryTypes = dynamicType.getAuxiliaryTypes();
2030  1 Map<TypeDescription, LoadedTypeInitializer> loadedTypeInitializers = dynamicType.getLoadedTypeInitializers();
2031  1 if (!auxiliaryTypes.isEmpty()) {
2032  1 for (Map.Entry<TypeDescription, Class<?>> entry : injectorFactory.resolve().inject(auxiliaryTypes).entrySet()) {
2033  2 loadedTypeInitializers.get(entry.getKey()).onLoad(entry.getValue());
2034    }
2035    }
2036  1 LoadedTypeInitializer loadedTypeInitializer = loadedTypeInitializers.get(dynamicType.getTypeDescription());
2037  1 if (loadedTypeInitializer.isAlive()) {
2038  1 NexusAccessor.INSTANCE.register(dynamicType.getTypeDescription().getName(), classLoader, identification, loadedTypeInitializer);
2039    }
2040    }
2041   
 
2042  2 toggle @Override
2043    public String toString() {
2044  2 return "AgentBuilder.InitializationStrategy.SelfInjection.Dispatcher.Eager{identification=" + identification + "}";
2045    }
2046    }
2047   
2048    /**
2049    * A type initializer that injects all auxiliary types of the instrumented type.
2050    */
 
2051    protected static class InjectingInitializer implements LoadedTypeInitializer {
2052   
2053    /**
2054    * The instrumented type.
2055    */
2056    private final TypeDescription instrumentedType;
2057   
2058    /**
2059    * The auxiliary types mapped to their class file representation.
2060    */
2061    private final Map<TypeDescription, byte[]> rawAuxiliaryTypes;
2062   
2063    /**
2064    * The instrumented types and auxiliary types mapped to their loaded type initializers.
2065    * The instrumented types and auxiliary types mapped to their loaded type initializers.
2066    */
2067    private final Map<TypeDescription, LoadedTypeInitializer> loadedTypeInitializers;
2068   
2069    /**
2070    * The class injector to use.
2071    */
2072    private final ClassInjector classInjector;
2073   
2074    /**
2075    * Creates a new injection initializer.
2076    *
2077    * @param instrumentedType The instrumented type.
2078    * @param rawAuxiliaryTypes The auxiliary types mapped to their class file representation.
2079    * @param loadedTypeInitializers The instrumented types and auxiliary types mapped to their loaded type initializers.
2080    * @param classInjector The class injector to use.
2081    */
 
2082  28 toggle protected InjectingInitializer(TypeDescription instrumentedType,
2083    Map<TypeDescription, byte[]> rawAuxiliaryTypes,
2084    Map<TypeDescription, LoadedTypeInitializer> loadedTypeInitializers,
2085    ClassInjector classInjector) {
2086  28 this.instrumentedType = instrumentedType;
2087  28 this.rawAuxiliaryTypes = rawAuxiliaryTypes;
2088  28 this.loadedTypeInitializers = loadedTypeInitializers;
2089  28 this.classInjector = classInjector;
2090    }
2091   
 
2092  22 toggle @Override
2093    public void onLoad(Class<?> type) {
2094  22 for (Map.Entry<TypeDescription, Class<?>> auxiliary : classInjector.inject(rawAuxiliaryTypes).entrySet()) {
2095  19 loadedTypeInitializers.get(auxiliary.getKey()).onLoad(auxiliary.getValue());
2096    }
2097  22 loadedTypeInitializers.get(instrumentedType).onLoad(type);
2098    }
2099   
 
2100  22 toggle @Override
2101    public boolean isAlive() {
2102  22 return true;
2103    }
2104   
 
2105  8 toggle @Override
2106    public boolean equals(Object o) {
2107  1 if (this == o) return true;
2108  2 if (o == null || getClass() != o.getClass()) return false;
2109  5 InjectingInitializer that = (InjectingInitializer) o;
2110  5 return classInjector.equals(that.classInjector)
2111    && instrumentedType.equals(that.instrumentedType)
2112    && rawAuxiliaryTypes.equals(that.rawAuxiliaryTypes)
2113    && loadedTypeInitializers.equals(that.loadedTypeInitializers);
2114    }
2115   
 
2116  6 toggle @Override
2117    public int hashCode() {
2118  6 int result = instrumentedType.hashCode();
2119  6 result = 31 * result + rawAuxiliaryTypes.hashCode();
2120  6 result = 31 * result + loadedTypeInitializers.hashCode();
2121  6 result = 31 * result + classInjector.hashCode();
2122  6 return result;
2123    }
2124   
 
2125  6 toggle @Override
2126    public String toString() {
2127  6 return "AgentBuilder.InitializationStrategy.SelfInjection.Dispatcher.InjectingInitializer{" +
2128    "instrumentedType=" + instrumentedType +
2129    ", rawAuxiliaryTypes=" + rawAuxiliaryTypes +
2130    ", loadedTypeInitializers=" + loadedTypeInitializers +
2131    ", classInjector=" + classInjector +
2132    '}';
2133    }
2134    }
2135    }
2136   
2137    /**
2138    * An accessor for making sure that the accessed {@link net.bytebuddy.agent.builder.Nexus} is the class that is loaded by the system class loader.
2139    */
 
2140    protected enum NexusAccessor {
2141   
2142    /**
2143    * The singleton instance.
2144    */
2145    INSTANCE;
2146   
2147    /**
2148    * The dispatcher for registering type initializers in the {@link Nexus}.
2149    */
2150    private final Dispatcher dispatcher;
2151   
2152    /**
2153    * The {@link ClassLoader#getSystemClassLoader()} method.
2154    */
2155    private final MethodDescription.InDefinedShape getSystemClassLoader;
2156   
2157    /**
2158    * The {@link java.lang.ClassLoader#loadClass(String)} method.
2159    */
2160    private final MethodDescription.InDefinedShape loadClass;
2161   
2162    /**
2163    * The {@link Integer#valueOf(int)} method.
2164    */
2165    private final MethodDescription.InDefinedShape valueOf;
2166   
2167    /**
2168    * The {@link java.lang.Class#getDeclaredMethod(String, Class[])} method.
2169    */
2170    private final MethodDescription getDeclaredMethod;
2171   
2172    /**
2173    * The {@link java.lang.reflect.Method#invoke(Object, Object...)} method.
2174    */
2175    private final MethodDescription invokeMethod;
2176   
2177    /**
2178    * Creates the singleton accessor.
2179    */
 
2180  3 toggle @SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "Explicit delegation of the exception")
2181    NexusAccessor() {
2182  3 Dispatcher dispatcher;
2183  3 try {
2184  3 TypeDescription nexusType = new TypeDescription.ForLoadedType(Nexus.class);
2185  3 dispatcher = new Dispatcher.Available(ClassInjector.UsingReflection.ofSystemClassLoader()
2186    .inject(Collections.singletonMap(nexusType, ClassFileLocator.ForClassLoader.read(Nexus.class).resolve()))
2187    .get(nexusType)
2188    .getDeclaredMethod("register", String.class, ClassLoader.class, int.class, Object.class));
2189    } catch (Exception exception) {
2190  1 try {
2191  1 dispatcher = new Dispatcher.Available(ClassLoader.getSystemClassLoader()
2192    .loadClass(Nexus.class.getName())
2193    .getDeclaredMethod("register", String.class, ClassLoader.class, int.class, Object.class));
2194    } catch (Exception ignored) {
2195  0 dispatcher = new Dispatcher.Unavailable(exception);
2196    }
2197    }
2198  3 this.dispatcher = dispatcher;
2199  3 getSystemClassLoader = new TypeDescription.ForLoadedType(ClassLoader.class).getDeclaredMethods()
2200    .filter(named("getSystemClassLoader").and(takesArguments(0))).getOnly();
2201  3 loadClass = new TypeDescription.ForLoadedType(ClassLoader.class).getDeclaredMethods()
2202    .filter(named("loadClass").and(takesArguments(String.class))).getOnly();
2203  3 getDeclaredMethod = new TypeDescription.ForLoadedType(Class.class).getDeclaredMethods()
2204    .filter(named("getDeclaredMethod").and(takesArguments(String.class, Class[].class))).getOnly();
2205  3 invokeMethod = new TypeDescription.ForLoadedType(Method.class).getDeclaredMethods()
2206    .filter(named("invoke").and(takesArguments(Object.class, Object[].class))).getOnly();
2207  3 valueOf = new TypeDescription.ForLoadedType(Integer.class).getDeclaredMethods()
2208    .filter(named("valueOf").and(takesArguments(int.class))).getOnly();
2209    }
2210   
2211    /**
2212    * Registers a type initializer with the class loader's nexus.
2213    *
2214    * @param name The name of a type for which a loaded type initializer is registered.
2215    * @param classLoader The class loader for which a loaded type initializer is registered.
2216    * @param identification An identification for the initializer to run.
2217    * @param typeInitializer The loaded type initializer to be registered.
2218    */
 
2219  29 toggle public void register(String name, ClassLoader classLoader, int identification, LoadedTypeInitializer typeInitializer) {
2220  29 dispatcher.register(name, classLoader, identification, typeInitializer);
2221    }
2222   
2223    /**
2224    * Creates a byte code appender for injecting a self-initializing type initializer block into the generated class.
2225    *
2226    * @param identification The identification of the initialization.
2227    * @return An appropriate byte code appender.
2228    */
 
2229  70 toggle public ByteCodeAppender identifiedBy(int identification) {
2230  70 return new InitializationAppender(identification);
2231    }
2232   
 
2233  1 toggle @Override
2234    public String toString() {
2235  1 return "AgentBuilder.InitializationStrategy.SelfInjection.NexusAccessor." + name();
2236    }
2237   
2238    /**
2239    * A dispatcher for registering type initializers in the {@link Nexus}.
2240    */
 
2241    protected interface Dispatcher {
2242   
2243    /**
2244    * Registers a type initializer with the class loader's nexus.
2245    *
2246    * @param name The name of a type for which a loaded type initializer is registered.
2247    * @param classLoader The class loader for which a loaded type initializer is registered.
2248    * @param identification An identification for the initializer to run.
2249    * @param typeInitializer The loaded type initializer to be registered.
2250    */
2251    void register(String name, ClassLoader classLoader, int identification, LoadedTypeInitializer typeInitializer);
2252   
2253    /**
2254    * An enabled dispatcher for registering a type initializer in a {@link Nexus}.
2255    */
 
2256    class Available implements Dispatcher {
2257   
2258    /**
2259    * Indicates that a static method is invoked by reflection.
2260    */
2261    private static final Object STATIC_METHOD = null;
2262   
2263    /**
2264    * The method for registering a type initializer in the system class loader's {@link Nexus}.
2265    */
2266    private final Method registration;
2267   
2268    /**
2269    * Creates a new dispatcher.
2270    *
2271    * @param registration The method for registering a type initializer in the system class loader's {@link Nexus}.
2272    */
 
2273  6 toggle protected Available(Method registration) {
2274  6 this.registration = registration;
2275    }
2276   
 
2277  29 toggle @Override
2278    public void register(String name, ClassLoader classLoader, int identification, LoadedTypeInitializer typeInitializer) {
2279  29 try {
2280  29 registration.invoke(STATIC_METHOD, name, classLoader, identification, typeInitializer);
2281    } catch (IllegalAccessException exception) {
2282  0 throw new IllegalStateException("Cannot register type initializer for " + name, exception);
2283    } catch (InvocationTargetException exception) {
2284  0 throw new IllegalStateException("Cannot register type initializer for " + name, exception.getCause());
2285    }
2286    }
2287   
 
2288  5 toggle @Override
2289    public boolean equals(Object other) {
2290  5 return this == other || !(other == null || getClass() != other.getClass())
2291    && registration.equals(((Available) other).registration);
2292    }
2293   
 
2294  3 toggle @Override
2295    public int hashCode() {
2296  3 return registration.hashCode();
2297    }
2298   
 
2299  3 toggle @Override
2300    public String toString() {
2301  3 return "AgentBuilder.InitializationStrategy.SelfInjection.NexusAccessor.Dispatcher.Available{" +
2302    "registration=" + registration +
2303    '}';
2304    }
2305    }
2306   
2307    /**
2308    * A disabled dispatcher where a {@link Nexus} is not available.
2309    */
 
2310    class Unavailable implements Dispatcher {
2311   
2312    /**
2313    * The exception that was raised during the dispatcher initialization.
2314    */
2315    private final Exception exception;
2316   
2317    /**
2318    * Creates a new disabled dispatcher.
2319    *
2320    * @param exception The exception that was raised during the dispatcher initialization.
2321    */
 
2322  4 toggle protected Unavailable(Exception exception) {
2323  4 this.exception = exception;
2324    }
2325   
 
2326  1 toggle @Override
2327    public void register(String name, ClassLoader classLoader, int identification, LoadedTypeInitializer typeInitializer) {
2328  1 throw new IllegalStateException("Could not locate registration method", exception);
2329    }
2330   
 
2331  5 toggle @Override
2332    public boolean equals(Object other) {
2333  5 return this == other || !(other == null || getClass() != other.getClass())
2334    && exception.equals(((Unavailable) other).exception);
2335    }
2336   
 
2337  3 toggle @Override
2338    public int hashCode() {
2339  3 return exception.hashCode();
2340    }
2341   
 
2342  3 toggle @Override
2343    public String toString() {
2344  3 return "AgentBuilder.InitializationStrategy.SelfInjection.NexusAccessor.Dispatcher.Unavailable{" +
2345    "exception=" + exception +
2346    '}';
2347    }
2348    }
2349    }
2350   
2351    /**
2352    * A byte code appender for invoking a Nexus for initializing the instrumented type.
2353    */
 
2354    protected static class InitializationAppender implements ByteCodeAppender {
2355   
2356    /**
2357    * The identification for the self-initialization to execute.
2358    */
2359    private final int identification;
2360   
2361    /**
2362    * Creates a new initialization appender.
2363    *
2364    * @param identification The identification for the self-initialization to execute.
2365    */
 
2366  73 toggle protected InitializationAppender(int identification) {
2367  73 this.identification = identification;
2368    }
2369   
 
2370  64 toggle @Override
2371    public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) {
2372  64 return new ByteCodeAppender.Simple(new StackManipulation.Compound(
2373    MethodInvocation.invoke(NexusAccessor.INSTANCE.getSystemClassLoader),
2374    new TextConstant(Nexus.class.getName()),
2375    MethodInvocation.invoke(NexusAccessor.INSTANCE.loadClass),
2376    new TextConstant("initialize"),
2377    ArrayFactory.forType(new TypeDescription.Generic.OfNonGenericType.ForLoadedType(Class.class))
2378    .withValues(Arrays.asList(
2379    ClassConstant.of(TypeDescription.CLASS),
2380    ClassConstant.of(new TypeDescription.ForLoadedType(int.class)))),
2381    MethodInvocation.invoke(NexusAccessor.INSTANCE.getDeclaredMethod),
2382    NullConstant.INSTANCE,
2383    ArrayFactory.forType(TypeDescription.Generic.OBJECT)
2384    .withValues(Arrays.asList(
2385    ClassConstant.of(instrumentedMethod.getDeclaringType().asErasure()),
2386    new StackManipulation.Compound(
2387    IntegerConstant.forValue(identification),
2388    MethodInvocation.invoke(INSTANCE.valueOf)))),
2389    MethodInvocation.invoke(NexusAccessor.INSTANCE.invokeMethod),
2390    Removal.SINGLE
2391    )).apply(methodVisitor, implementationContext, instrumentedMethod);
2392    }
2393   
 
2394  11 toggle @Override
2395    public boolean equals(Object other) {
2396  1 if (this == other) return true;
2397  2 if (other == null || getClass() != other.getClass()) return false;
2398  8 InitializationAppender that = (InitializationAppender) other;
2399  8 return identification == that.identification;
2400    }
2401   
 
2402  3 toggle @Override
2403    public int hashCode() {
2404  3 return identification;
2405    }
2406   
 
2407  3 toggle @Override
2408    public String toString() {
2409  3 return "AgentBuilder.InitializationStrategy.SelfInjection.NexusAccessor.InitializationAppender{" +
2410    "identification=" + identification +
2411    '}';
2412    }
2413    }
2414    }
2415    }
2416   
2417    /**
2418    * An initialization strategy that loads auxiliary types before loading the instrumented type. This strategy skips all types
2419    * that are a subtype of the instrumented type which would cause a premature loading of the instrumented type and abort
2420    * the instrumentation process.
2421    */
 
2422    enum Minimal implements InitializationStrategy, Dispatcher {
2423   
2424    /**
2425    * The singleton instance.
2426    */
2427    INSTANCE;
2428   
 
2429  1 toggle @Override
2430    public Dispatcher dispatcher() {
2431  1 return this;
2432    }
2433   
 
2434  1 toggle @Override
2435    public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder) {
2436  1 return builder;
2437    }
2438   
 
2439  2 toggle @Override
2440    public void register(DynamicType dynamicType, ClassLoader classLoader, InjectorFactory injectorFactory) {
2441  2 Map<TypeDescription, byte[]> auxiliaryTypes = dynamicType.getAuxiliaryTypes();
2442  2 Map<TypeDescription, byte[]> independentTypes = new LinkedHashMap<TypeDescription, byte[]>(auxiliaryTypes);
2443  2 for (TypeDescription auxiliaryType : auxiliaryTypes.keySet()) {
2444  3 if (!auxiliaryType.getDeclaredAnnotations().isAnnotationPresent(AuxiliaryType.SignatureRelevant.class)) {
2445  2 independentTypes.remove(auxiliaryType);
2446    }
2447    }
2448  2 if (!independentTypes.isEmpty()) {
2449  1 ClassInjector classInjector = injectorFactory.resolve();
2450  1 Map<TypeDescription, LoadedTypeInitializer> loadedTypeInitializers = dynamicType.getLoadedTypeInitializers();
2451  1 for (Map.Entry<TypeDescription, Class<?>> entry : classInjector.inject(independentTypes).entrySet()) {
2452  1 loadedTypeInitializers.get(entry.getKey()).onLoad(entry.getValue());
2453    }
2454    }
2455    }
2456   
 
2457  1 toggle @Override
2458    public String toString() {
2459  1 return "AgentBuilder.InitializationStrategy.Minimal." + name();
2460    }
2461    }
2462    }
2463   
2464    /**
2465    * A description strategy is responsible for resolving a {@link TypeDescription} when transforming or retransforming/-defining a type.
2466    */
 
2467    interface DescriptionStrategy {
2468   
2469    /**
2470    * Describes the given type.
2471    *
2472    * @param typeName The binary name of the type to describe.
2473    * @param typeBeingRedefined The type that is being redefined, if a redefinition is applied or {@code null} if no redefined type is available.
2474    * @param typeLocator The type locator to use.
2475    * @param classLoader The class loader of the type to be described.
2476    * @param classFileLocator The class file locator of the type to be described.
2477    * @return An appropriate type description.
2478    */
2479    TypeDescription apply(String typeName, Class<?> typeBeingRedefined, TypeLocator typeLocator, ClassLoader classLoader, ClassFileLocator classFileLocator);
2480   
2481    /**
2482    * Describes the given type.
2483    *
2484    * @param type The loaded type to be described.
2485    * @param typeLocator The type locator to use.
2486    * @return An appropriate type description.
2487    */
2488    TypeDescription apply(Class<?> type, TypeLocator typeLocator);
2489   
2490    /**
2491    * Default implementations of a {@link DescriptionStrategy}.
2492    */
 
2493    enum Default implements DescriptionStrategy {
2494   
2495    /**
2496    * A description type strategy represents a type as a {@link net.bytebuddy.description.type.TypeDescription.ForLoadedType} if a
2497    * retransformation or redefinition is applied on a type. Using a loaded type typically results in better performance as no
2498    * I/O is required for resolving type descriptions. However, any interaction with the type is carried out via the Java reflection
2499    * API. Using the reflection API triggers eager loading of any type that is part of a method or field signature. If any of these
2500    * types are missing from the class path, this eager loading will cause a {@link NoClassDefFoundError}. Some Java code declares
2501    * optional dependencies to other classes which are only realized if the optional dependency is present. Such code relies on the
2502    * Java reflection API not being used for types using optional dependencies.
2503    */
2504    HYBRID {
 
2505  275 toggle @Override
2506    public TypeDescription apply(String typeName,
2507    Class<?> typeBeingRedefined,
2508    TypeLocator typeLocator,
2509    ClassLoader classLoader,
2510    ClassFileLocator classFileLocator) {
2511  275 return typeBeingRedefined == null
2512    ? POOL_ONLY.apply(typeName, UNAVAILABLE, typeLocator, classLoader, classFileLocator)
2513    : new TypeDescription.ForLoadedType(typeBeingRedefined);
2514    }
2515   
 
2516  191215 toggle @Override
2517    public TypeDescription apply(Class<?> type, TypeLocator typeLocator) {
2518  191215 return new TypeDescription.ForLoadedType(type);
2519    }
2520    },
2521   
2522    /**
2523    * <p>
2524    * A description strategy that always describes Java types using a {@link TypePool}. This requires that any type - even if it is already
2525    * loaded and a {@link Class} instance is available - is processed as a non-loaded type description. Doing so can cause overhead as processing
2526    * loaded types is supported very efficiently by a JVM.
2527    * </p>
2528    * <p>
2529    * Avoiding the usage of loaded types can improve robustness as this approach does not rely on the Java reflection API which triggers eager
2530    * validation of this loaded type which can fail an application if optional types are used by any types field or method signatures. Also, it
2531    * is possible to guarantee debugging meta data to be available also for retransformed or redefined types if a {@link TypeStrategy} specifies
2532    * the extraction of such meta data.
2533    * </p>
2534    */
2535    POOL_ONLY {
 
2536  227 toggle @Override
2537    public TypeDescription apply(String typeName,
2538    Class<?> typeBeingRedefined,
2539    TypeLocator typeLocator,
2540    ClassLoader classLoader,
2541    ClassFileLocator classFileLocator) {
2542  227 return typeLocator.typePool(classFileLocator, classLoader).describe(typeName).resolve();
2543    }
2544   
 
2545  47905 toggle @Override
2546    public TypeDescription apply(Class<?> type, TypeLocator typeLocator) {
2547  47905 return typeLocator.typePool(ClassFileLocator.ForClassLoader.of(type.getClassLoader()), type.getClassLoader()).describe(TypeDescription.ForLoadedType.getName(type)).resolve();
2548    }
2549    };
2550   
2551    /**
2552    * Indicates that no loaded type is available.
2553    */
2554    private static final Class<?> UNAVAILABLE = null;
2555   
 
2556  34 toggle @Override
2557    public String toString() {
2558  34 return "AgentBuilder.DescriptionStrategy.Default." + name();
2559    }
2560    }
2561    }
2562   
2563    /**
2564    * An installation strategy determines the reaction to a raised exception after the registration of a {@link ClassFileTransformer}.
2565    */
 
2566    interface InstallationStrategy {
2567   
2568    /**
2569    * Handles an error that occured after registering a class file transformer during installation.
2570    *
2571    * @param instrumentation The instrumentation onto which the class file transformer was registered.
2572    * @param classFileTransformer The class file transformer that was registered.
2573    * @param throwable The error that occurred.
2574    * @return The class file transformer to return when an error occurred.
2575    */
2576    ClassFileTransformer onError(Instrumentation instrumentation, ClassFileTransformer classFileTransformer, Throwable throwable);
2577   
2578    /**
2579    * Default implementations of installation strategies.
2580    */
 
2581    enum Default implements InstallationStrategy {
2582   
2583    /**
2584    * An installation strategy that unregisters the transformer and propagates the exception. Using this strategy does not guarantee
2585    * that the registered transformer was not applied to any class, nor does it attempt to revert previous transformations. It only
2586    * guarantees that the class file transformer is unregistered and does no longer apply after this method returns.
2587    */
2588    ESCALATING {
 
2589  1 toggle @Override
2590    public ClassFileTransformer onError(Instrumentation instrumentation, ClassFileTransformer classFileTransformer, Throwable throwable) {
2591  1 instrumentation.removeTransformer(classFileTransformer);
2592  1 throw new IllegalStateException("Could not install class file transformer", throwable);
2593    }
2594    },
2595   
2596    /**
2597    * An installation strategy that retains the class file transformer and suppresses the error.
2598    */
2599    SUPPRESSING {
 
2600  1 toggle @Override
2601    public ClassFileTransformer onError(Instrumentation instrumentation, ClassFileTransformer classFileTransformer, Throwable throwable) {
2602  1 return classFileTransformer;
2603    }
2604    };
2605   
 
2606  34 toggle @Override
2607    public String toString() {
2608  34 return "AgentBuilder.InstallationStrategy.Default." + name();
2609    }
2610    }
2611    }
2612   
2613    /**
2614    * A redefinition strategy regulates how already loaded classes are modified by a built agent.
2615    */
 
2616    enum RedefinitionStrategy {
2617   
2618    /**
2619    * Disables redefinition such that already loaded classes are not affected by the agent.
2620    */
2621    DISABLED {
 
2622  90 toggle @Override
2623    protected boolean isRetransforming(Instrumentation instrumentation) {
2624  90 return false;
2625    }
2626   
 
2627  0 toggle @Override
2628    protected Collector makeCollector(Default.Transformation transformation) {
2629  0 throw new IllegalStateException("A disabled redefinition strategy cannot create a collector");
2630    }
2631    },
2632   
2633    /**
2634    * <p>
2635    * Applies a <b>redefinition</b> to all classes that are already loaded and that would have been transformed if
2636    * the built agent was registered before they were loaded. The created {@link ClassFileTransformer} is <b>not</b>
2637    * registered for applying retransformations.
2638    * </p>
2639    * <p>
2640    * Using this strategy, a redefinition is applied as a single transformation request. This means that a single illegal
2641    * redefinition of a class causes the entire redefinition attempt to fail.
2642    * </p>
2643    * <p>
2644    * <b>Note</b>: When applying a redefinition, it is normally required to use a {@link TypeStrategy} that applies
2645    * a redefinition instead of rebasing classes such as {@link TypeStrategy.Default#REDEFINE}. Also, consider
2646    * the constrains given by this type strategy.
2647    * </p>
2648    */
2649    REDEFINITION {
 
2650  38 toggle @Override
2651    protected boolean isRetransforming(Instrumentation instrumentation) {
2652  38 if (!instrumentation.isRedefineClassesSupported()) {
2653  3 throw new IllegalArgumentException("Cannot redefine classes: " + instrumentation);
2654    }
2655  35 return false;
2656    }
2657   
 
2658  23 toggle @Override
2659    protected Collector makeCollector(Default.Transformation transformation) {
2660  23 return new Collector.ForRedefinition.Cumulative(transformation);
2661    }
2662    },
2663   
2664    /**
2665    * <p>
2666    * Applies a <b>redefinition</b> to all classes that are already loaded and that would have been transformed if
2667    * the built agent was registered before they were loaded. The created {@link ClassFileTransformer} is <b>not</b>
2668    * registered for applying retransformations.
2669    * </p>
2670    * <p>
2671    * Using this strategy, a redefinition is applied in single class chunks. This means that a single illegal
2672    * redefinition of a class does not cause the failure of any other redefinition. Chunking the redefinition does
2673    * however imply a performance penalty. If at least one redefinition has failed, applying this strategy still causes an
2674    * exception to be thrown as a result of the application.
2675    * </p>
2676    * <p>
2677    * <b>Note</b>: When applying a redefinition, it is normally required to use a {@link TypeStrategy} that applies
2678    * a redefinition instead of rebasing classes such as {@link TypeStrategy.Default#REDEFINE}. Also, consider
2679    * the constrains given by this type strategy.
2680    * </p>
2681    */
2682    REDEFINITION_CHUNKED {
 
2683  12 toggle @Override
2684    protected boolean isRetransforming(Instrumentation instrumentation) {
2685  12 return REDEFINITION.isRetransforming(instrumentation);
2686    }
2687   
 
2688  10 toggle @Override
2689    protected Collector makeCollector(Default.Transformation transformation) {
2690  10 return new Collector.ForRedefinition.Chunked(transformation);
2691    }
2692    },
2693   
2694    /**
2695    * <p>
2696    * Applies a <b>retransformation</b> to all classes that are already loaded and that would have been transformed if
2697    * the built agent was registered before they were loaded. The created {@link ClassFileTransformer} is registered
2698    * for applying retransformations.
2699    * </p>
2700    * <p>
2701    * Using this strategy, a retransformation is applied as a single transformation request. This means that a single illegal
2702    * retransformation of a class causes the entire retransformation attempt to fail.
2703    * </p>
2704    * <p>
2705    * <b>Note</b>: When applying a redefinition, it is normally required to use a {@link TypeStrategy} that applies
2706    * a redefinition instead of rebasing classes such as {@link TypeStrategy.Default#REDEFINE}. Also, consider
2707    * the constrains given by this type strategy.
2708    * </p>
2709    */
2710    RETRANSFORMATION {
 
2711  34 toggle @Override
2712    protected boolean isRetransforming(Instrumentation instrumentation) {
2713  34 if (!instrumentation.isRetransformClassesSupported()) {
2714  3 throw new IllegalArgumentException("Cannot retransform classes: " + instrumentation);
2715    }
2716  31 return true;
2717    }
2718   
 
2719  19 toggle @Override
2720    protected Collector makeCollector(Default.Transformation transformation) {
2721  19 return new Collector.ForRetransformation.Cumulative(transformation);
2722    }
2723    },
2724   
2725    /**
2726    * <p>
2727    * Applies a <b>retransformation</b> to all classes that are already loaded and that would have been transformed if
2728    * the built agent was registered before they were loaded. The created {@link ClassFileTransformer} is registered
2729    * for applying retransformations.
2730    * </p>
2731    * <p>
2732    * Using this strategy, a retransformation is applied in single class chunks. This means that a single illegal
2733    * retransformation of a class does not cause the failure of any other redefinition. Chunking the retransformation does
2734    * however imply a performance penalty. If at least one retransformation has failed, applying this strategy still causes an
2735    * exception to be thrown as a result of the application.
2736    * </p>
2737    * <p>
2738    * <b>Note</b>: When applying a redefinition, it is normally required to use a {@link TypeStrategy} that applies
2739    * a redefinition instead of rebasing classes such as {@link TypeStrategy.Default#REDEFINE}. Also, consider
2740    * the constrains given by this type strategy.
2741    * </p>
2742    */
2743    RETRANSFORMATION_CHUNKED {
 
2744  12 toggle @Override
2745    protected boolean isRetransforming(Instrumentation instrumentation) {
2746  12 return RETRANSFORMATION.isRetransforming(instrumentation);
2747    }
2748   
 
2749  10 toggle @Override
2750    protected Collector makeCollector(Default.Transformation transformation) {
2751  10 return new Collector.ForRetransformation.Chunked(transformation);
2752    }
2753    };
2754   
2755    /**
2756    * Indicates if this strategy requires a class file transformer to be registered with a hint to apply the
2757    * transformer for retransformation.
2758    *
2759    * @param instrumentation The instrumentation instance used.
2760    * @return {@code true} if a class file transformer must be registered with a hint for retransformation.
2761    */
2762    protected abstract boolean isRetransforming(Instrumentation instrumentation);
2763   
2764    /**
2765    * Indicates that this redefinition strategy applies a modification of already loaded classes.
2766    *
2767    * @return {@code true} if this redefinition strategy applies a modification of already loaded classes.
2768    */
 
2769  156 toggle protected boolean isEnabled() {
2770  156 return this != DISABLED;
2771    }
2772   
2773    /**
2774    * Creates a collector instance that is responsible for collecting loaded classes for potential retransformation.
2775    *
2776    * @param transformation The transformation that is registered for the agent.
2777    * @return A new collector for collecting already loaded classes for transformation.
2778    */
2779    protected abstract Collector makeCollector(Default.Transformation transformation);
2780   
 
2781  53 toggle @Override
2782    public String toString() {
2783  53 return "AgentBuilder.RedefinitionStrategy." + name();
2784    }
2785   
2786    /**
2787    * A collector is responsible for collecting classes that are to be considered for modification.
2788    */
 
2789    protected interface Collector {
2790   
2791    /**
2792    * Considers a loaded class for modification.
2793    *
2794    * @param typeDescription The type description of the type that is to be considered.
2795    * @param type The loaded representation of the type that is to be considered.
2796    * @param ignoredTypeMatcher Identifies types that should not be instrumented.
2797    * @return {@code true} if the class is considered to be redefined.
2798    */
2799    boolean consider(TypeDescription typeDescription, Class<?> type, RawMatcher ignoredTypeMatcher);
2800   
2801    /**
2802    * Applies this collector.
2803    *
2804    * @param instrumentation The instrumentation instance to apply the transformation for.
2805    * @param typeLocator The type locator to use.
2806    * @param listener the listener to notify.
2807    * @throws UnmodifiableClassException If a class is not modifiable.
2808    * @throws ClassNotFoundException If a class could not be found.
2809    */
2810    void apply(Instrumentation instrumentation,
2811    TypeLocator typeLocator,
2812    Listener listener) throws UnmodifiableClassException, ClassNotFoundException;
2813   
2814    /**
2815    * A collector that applies a <b>redefinition</b> of already loaded classes.
2816    */
 
2817    abstract class ForRedefinition implements Collector {
2818   
2819    /**
2820    * The transformation of the built agent.
2821    */
2822    protected final Default.Transformation transformation;
2823   
2824    /**
2825    * A list of already collected redefinitions.
2826    */
2827    protected final List<Entry> entries;
2828   
2829    /**
2830    * Creates a new collector for a redefinition.
2831    *
2832    * @param transformation The transformation of the built agent.
2833    */
 
2834  37 toggle protected ForRedefinition(Default.Transformation transformation) {
2835  37 this.transformation = transformation;
2836  37 entries = new ArrayList<Entry>();
2837    }
2838   
 
2839  108601 toggle @Override
2840    public boolean consider(TypeDescription typeDescription, Class<?> type, RawMatcher ignoredTypeMatcher) {
2841  108601 return transformation.resolve(typeDescription,
2842    type.getClassLoader(),
2843    JavaModule.ofType(type),
2844    type,
2845    type.getProtectionDomain(),
2846    ignoredTypeMatcher).getSort().isAlive() && entries.add(new Entry(type));
2847    }
2848   
 
2849  33 toggle @Override
2850    public void apply(Instrumentation instrumentation, TypeLocator typeLocator, Listener listener) throws UnmodifiableClassException, ClassNotFoundException {
2851  33 List<ClassDefinition> classDefinitions = new ArrayList<ClassDefinition>(entries.size());
2852  33 for (Entry entry : entries) {
2853  17 JavaModule module = JavaModule.ofType(entry.getType());
2854  17 try {
2855  17 classDefinitions.add(entry.resolve(ClassFileLocator.ForClassLoader.of(entry.getType().getClassLoader())));
2856    } catch (Throwable throwable) {
2857  0 try {
2858  0 listener.onError(TypeDescription.ForLoadedType.getName(entry.getType()), entry.getType().getClassLoader(), module, throwable);
2859    } finally {
2860  0 listener.onComplete(TypeDescription.ForLoadedType.getName(entry.getType()), entry.getType().getClassLoader(), module);
2861    }
2862    }
2863    }
2864  33 doApply(instrumentation, classDefinitions);
2865    }
2866   
2867    /**
2868    * Applies a redefinition.
2869    *
2870    * @param instrumentation The instrumentation instance to use.
2871    * @param classDefinitions The class definitions to apply.
2872    * @throws UnmodifiableClassException If a class is not modifiable.
2873    * @throws ClassNotFoundException If a class could not be found.
2874    */
2875    protected abstract void doApply(Instrumentation instrumentation, List<ClassDefinition> classDefinitions) throws UnmodifiableClassException, ClassNotFoundException;
2876   
2877    /**
2878    * A collector that applies a redefinition and applies all redefinitions as a single transformation request.
2879    */
 
2880    protected static class Cumulative extends ForRedefinition {
2881   
2882    /**
2883    * Creates a new cumulative redefinition collector.
2884    *
2885    * @param transformation The transformation of the built agent.
2886    */
 
2887  25 toggle protected Cumulative(Default.Transformation transformation) {
2888  25 super(transformation);
2889    }
2890   
 
2891  23 toggle @Override
2892    protected void doApply(Instrumentation instrumentation, List<ClassDefinition> classDefinitions) throws UnmodifiableClassException, ClassNotFoundException {
2893  23 if (!classDefinitions.isEmpty()) {
2894  9 instrumentation.redefineClasses(classDefinitions.toArray(new ClassDefinition[classDefinitions.size()]));
2895    }
2896    }
2897   
 
2898  2 toggle @Override
2899    public String toString() {
2900  2 return "AgentBuilder.RedefinitionStrategy.Collector.ForRedefinition.Cumulative{" +
2901    "transformation=" + transformation +
2902    ", entries=" + entries +
2903    '}';
2904    }
2905    }
2906   
2907    /**
2908    * A collector that applies a redefinition and applies all redefinitions as a separate transformation request per class.
2909    */
 
2910    protected static class Chunked extends ForRedefinition {
2911   
2912    /**
2913    * Creates a new chunked redefinition collector.
2914    *
2915    * @param transformation The transformation of the built agent.
2916    */
 
2917  12 toggle protected Chunked(Default.Transformation transformation) {
2918  12 super(transformation);
2919    }
2920   
 
2921  10 toggle @Override
2922    protected void doApply(Instrumentation instrumentation, List<ClassDefinition> classDefinitions) throws UnmodifiableClassException, ClassNotFoundException {
2923  10 Map<Class<?>, Exception> exceptions = new HashMap<Class<?>, Exception>();
2924  10 for (ClassDefinition classDefinition : classDefinitions) {
2925  8 try {
2926  8 instrumentation.redefineClasses(classDefinition);
2927    } catch (Exception exception) {
2928  2 exceptions.put(classDefinition.getDefinitionClass(), exception);
2929    }
2930    }
2931  10 if (!exceptions.isEmpty()) {
2932  1 throw new IllegalStateException("Could not retransform at least one class: " + exceptions);
2933    }
2934    }
2935   
 
2936  2 toggle @Override
2937    public String toString() {
2938  2 return "AgentBuilder.RedefinitionStrategy.Collector.ForRedefinition.Chunked{" +
2939    "transformation=" + transformation +
2940    ", entries=" + entries +
2941    '}';
2942    }
2943    }
2944   
2945    /**
2946    * An entry describing a type redefinition.
2947    */
 
2948    protected static class Entry {
2949   
2950    /**
2951    * The type to be redefined.
2952    */
2953    private final Class<?> type;
2954   
2955    /**
2956    * Creates a new entry for a given type.
2957    *
2958    * @param type The type to be redefined.
2959    */
 
2960  20 toggle protected Entry(Class<?> type) {
2961  20 this.type = type;
2962    }
2963   
2964    /**
2965    * Returns the type that is being redefined.
2966    *
2967    * @return The type that is being redefined.
2968    */
 
2969  34 toggle public Class<?> getType() {
2970  34 return type;
2971    }
2972   
2973    /**
2974    * Resolves the entry to a class definition.
2975    *
2976    * @param classFileLocator The class file locator for locating the redefine type's class file.
2977    * @return A class definition representing the redefined class.
2978    * @throws IOException If an IO exception occurs.
2979    */
 
2980  17 toggle protected ClassDefinition resolve(ClassFileLocator classFileLocator) throws IOException {
2981  17 return new ClassDefinition(type, classFileLocator.locate(TypeDescription.ForLoadedType.getName(type)).resolve());
2982    }
2983   
 
2984  5 toggle @Override
2985    public boolean equals(Object other) {
2986  1 if (this == other) return true;
2987  2 if (other == null || getClass() != other.getClass()) return false;
2988  2 Entry entry = (Entry) other;
2989  2 return type.equals(entry.type);
2990    }
2991   
 
2992  3 toggle @Override
2993    public int hashCode() {
2994  3 return type.hashCode();
2995    }
2996   
 
2997  3 toggle @Override
2998    public String toString() {
2999  3 return "AgentBuilder.RedefinitionStrategy.Collector.ForRedefinition.Entry{" +
3000    "type=" + type +
3001    '}';
3002    }
3003    }
3004    }
3005   
3006    /**
3007    * A collector that applies a <b>retransformation</b> of already loaded classes.
3008    */
 
3009    abstract class ForRetransformation implements Collector {
3010   
3011    /**
3012    * The transformation defined by the built agent.
3013    */
3014    protected final Default.Transformation transformation;
3015   
3016    /**
3017    * The types that were collected for retransformation.
3018    */
3019    protected final List<Class<?>> types;
3020   
3021    /**
3022    * Creates a new collector for a retransformation.
3023    *
3024    * @param transformation The transformation defined by the built agent.
3025    */
 
3026  33 toggle protected ForRetransformation(Default.Transformation transformation) {
3027  33 this.transformation = transformation;
3028  33 types = new ArrayList<Class<?>>();
3029    }
3030   
 
3031  108494 toggle @Override
3032    public boolean consider(TypeDescription typeDescription, Class<?> type, RawMatcher ignoredTypeMatcher) {
3033  108494 return transformation.resolve(typeDescription,
3034    type.getClassLoader(),
3035    JavaModule.ofType(type),
3036    type,
3037    type.getProtectionDomain(),
3038    ignoredTypeMatcher).getSort().isAlive() && types.add(type);
3039    }
3040   
3041    /**
3042    * A collector that applies a retransformation and applies all redefinitions as a single transformation request.
3043    */
 
3044    protected static class Cumulative extends ForRetransformation {
3045   
3046    /**
3047    * Creates a new cumulative retransformation collector.
3048    *
3049    * @param transformation The transformation of the built agent.
3050    */
 
3051  21 toggle protected Cumulative(Default.Transformation transformation) {
3052  21 super(transformation);
3053    }
3054   
 
3055  19 toggle @Override
3056    public void apply(Instrumentation instrumentation, TypeLocator typeLocator, Listener listener) throws UnmodifiableClassException {
3057  19 if (!types.isEmpty()) {
3058  9 instrumentation.retransformClasses(types.toArray(new Class<?>[types.size()]));
3059    }
3060    }
3061   
 
3062  2 toggle @Override
3063    public String toString() {
3064  2 return "AgentBuilder.RedefinitionStrategy.Collector.ForRetransformation.Cumulative{" +
3065    "transformation=" + transformation +
3066    ", types=" + types +
3067    '}';
3068    }
3069    }
3070   
3071    /**
3072    * A collector that applies a retransformation and applies all redefinitions as a chunked transformation request.
3073    */
 
3074    protected static class Chunked extends ForRetransformation {
3075   
3076    /**
3077    * Creates a new chunked retransformation collector.
3078    *
3079    * @param transformation The transformation of the built agent.
3080    */
 
3081  12 toggle protected Chunked(Default.Transformation transformation) {
3082  12 super(transformation);
3083    }
3084   
 
3085  10 toggle @Override
3086    public void apply(Instrumentation instrumentation, TypeLocator typeLocator, Listener listener) throws UnmodifiableClassException {
3087  10 Map<Class<?>, Exception> exceptions = new HashMap<Class<?>, Exception>();
3088  10 for (Class<?> type : types) {
3089  8 try {
3090  8 instrumentation.retransformClasses(type);
3091    } catch (Exception exception) {
3092  1 exceptions.put(type, exception);
3093    }
3094    }
3095  10 if (!exceptions.isEmpty()) {
3096  1 throw new IllegalStateException("Could not retransform at least one class: " + exceptions);
3097    }
3098    }
3099   
 
3100  2 toggle @Override
3101    public String toString() {
3102  2 return "AgentBuilder.RedefinitionStrategy.Collector.ForRetransformation.Chunked{" +
3103    "transformation=" + transformation +
3104    ", types=" + types +
3105    '}';
3106    }
3107    }
3108    }
3109    }
3110    }
3111   
3112    /**
3113    * Implements the instrumentation of the {@code LambdaMetafactory} if this feature is enabled.
3114    */
 
3115    enum LambdaInstrumentationStrategy implements Callable<Class<?>> {
3116   
3117    /**
3118    * A strategy that enables instrumentation of the {@code LambdaMetafactory} if such a factory exists on the current VM.
3119    * Classes representing lambda expressions that are created by Byte Buddy are fully compatible to those created by
3120    * the JVM and can be serialized or deserialized to one another. The classes do however show a few differences:
3121    * <ul>
3122    * <li>Byte Buddy's classes are public with a public executing transformer. Doing so, it is not necessary to instantiate a
3123    * non-capturing lambda expression by reflection. This is done because Byte Buddy is not necessarily capable
3124    * of using reflection due to an active security manager.</li>
3125    * <li>Byte Buddy's classes are not marked as synthetic as an agent builder does not instrument synthetic classes
3126    * by default.</li>
3127    * </ul>
3128    */
3129    ENABLED {
 
3130  37 toggle @Override
3131    protected void apply(ByteBuddy byteBuddy, Instrumentation instrumentation, ClassFileTransformer classFileTransformer) {
3132  37 if (LambdaFactory.register(classFileTransformer, new LambdaInstanceFactory(byteBuddy), this)) {
3133  36 Class<?> lambdaMetaFactory;
3134  36 try {
3135  36 lambdaMetaFactory = Class.forName("java.lang.invoke.LambdaMetafactory");
3136    } catch (ClassNotFoundException ignored) {
3137  0 return;
3138    }
3139  36 byteBuddy.with(Implementation.Context.Disabled.Factory.INSTANCE)
3140    .redefine(lambdaMetaFactory)
3141    .visit(new AsmVisitorWrapper.ForDeclaredMethods()
3142    .method(named("metafactory"), MetaFactoryRedirection.INSTANCE)
3143    .method(named("altMetafactory"), AlternativeMetaFactoryRedirection.INSTANCE))
3144    .make()
3145    .load(lambdaMetaFactory.getClassLoader(), ClassReloadingStrategy.of(instrumentation));
3146    }
3147    }
3148   
 
3149  43 toggle @Override
3150    public Class<?> call() throws Exception {
3151  43 TypeDescription lambdaFactory = new TypeDescription.ForLoadedType(LambdaFactory.class);
3152  43 return ClassInjector.UsingReflection.ofSystemClassLoader()
3153    .inject(Collections.singletonMap(lambdaFactory, ClassFileLocator.ForClassLoader.read(LambdaFactory.class).resolve()))
3154    .get(lambdaFactory);
3155    }
3156    },
3157   
3158    /**
3159    * A strategy that does not instrument the {@code LambdaMetafactory}.
3160    */
3161    DISABLED {
 
3162  116 toggle @Override
3163    protected void apply(ByteBuddy byteBuddy, Instrumentation instrumentation, ClassFileTransformer classFileTransformer) {
3164    /* do nothing */
3165    }
3166   
 
3167  1 toggle @Override
3168    public Class<?> call() throws Exception {
3169  1 throw new IllegalStateException("Cannot inject LambdaFactory from disabled instrumentation strategy");
3170    }
3171    };
3172   
3173    /**
3174    * Indicates that an original implementation can be ignored when redefining a method.
3175    */
3176    protected static final MethodVisitor IGNORE_ORIGINAL = null;
3177   
3178    /**
3179    * Releases the supplied class file transformer when it was built with {@link AgentBuilder#with(LambdaInstrumentationStrategy)} enabled.
3180    * Subsequently, the class file transformer is no longer applied when a class that represents a lambda expression is created.
3181    *
3182    * @param classFileTransformer The class file transformer to release.
3183    * @param instrumentation The instrumentation instance that is used to potentially rollback the instrumentation of the {@code LambdaMetafactory}.
3184    */
 
3185  36 toggle public static void release(ClassFileTransformer classFileTransformer, Instrumentation instrumentation) {
3186  36 if (LambdaFactory.release(classFileTransformer)) {
3187  36 try {
3188  36 ClassReloadingStrategy.of(instrumentation).reset(Class.forName("java.lang.invoke.LambdaMetafactory"));
3189    } catch (Exception exception) {
3190  0 throw new IllegalStateException("Could not release lambda transformer", exception);
3191    }
3192    }
3193    }
3194   
3195    /**
3196    * Returns an enabled lambda instrumentation strategy for {@code true}.
3197    *
3198    * @param enabled If lambda instrumentation should be enabled.
3199    * @return {@code true} if the returned strategy should be enabled.
3200    */
 
3201  2 toggle public static LambdaInstrumentationStrategy of(boolean enabled) {
3202  2 return enabled
3203    ? ENABLED
3204    : DISABLED;
3205    }
3206   
3207    /**
3208    * Applies a transformation to lambda instances if applicable.
3209    *
3210    * @param byteBuddy The Byte Buddy instance to use.
3211    * @param instrumentation The instrumentation instance for applying a redefinition.
3212    * @param classFileTransformer The class file transformer to apply.
3213    */
3214    protected abstract void apply(ByteBuddy byteBuddy, Instrumentation instrumentation, ClassFileTransformer classFileTransformer);
3215   
3216    /**
3217    * Indicates if this strategy enables instrumentation of the {@code LambdaMetafactory}.
3218    *
3219    * @return {@code true} if this strategy is enabled.
3220    */
 
3221  2 toggle public boolean isEnabled() {
3222  2 return this == ENABLED;
3223    }
3224   
 
3225  50 toggle @Override
3226    public String toString() {
3227  50 return "AgentBuilder.LambdaInstrumentationStrategy." + name();
3228    }
3229   
3230    /**
3231    * A factory that creates instances that represent lambda expressions.
3232    */
 
3233    protected static class LambdaInstanceFactory {
3234   
3235    /**
3236    * The name of a factory for a lambda expression.
3237    */
3238    private static final String LAMBDA_FACTORY = "get$Lambda";
3239   
3240    /**
3241    * A prefix for a field that represents a property of a lambda expression.
3242    */
3243    private static final String FIELD_PREFIX = "arg$";
3244   
3245    /**
3246    * The infix to use for naming classes that represent lambda expression. The additional prefix
3247    * is necessary because the subsequent counter is not sufficient to keep names unique compared
3248    * to the original factory.
3249    */
3250    private static final String LAMBDA_TYPE_INFIX = "$$Lambda$ByteBuddy$";
3251   
3252    /**
3253    * A type-safe constant to express that a class is not already loaded when applying a class file transformer.
3254    */
3255    private static final Class<?> NOT_PREVIOUSLY_DEFINED = null;
3256   
3257    /**
3258    * A counter for naming lambda expressions randomly.
3259    */
3260    private static final AtomicInteger LAMBDA_NAME_COUNTER = new AtomicInteger();
3261   
3262    /**
3263    * The Byte Buddy instance to use for creating lambda objects.
3264    */
3265    private final ByteBuddy byteBuddy;
3266   
3267    /**
3268    * Creates a new lambda instance factory.
3269    *
3270    * @param byteBuddy The Byte Buddy instance to use for creating lambda objects.
3271    */
 
3272  40 toggle protected LambdaInstanceFactory(ByteBuddy byteBuddy) {
3273  40 this.byteBuddy = byteBuddy;
3274    }
3275   
3276    /**
3277    * Applies this lambda meta factory.
3278    *
3279    * @param targetTypeLookup A lookup context representing the creating class of this lambda expression.
3280    * @param lambdaMethodName The name of the lambda expression's represented method.
3281    * @param factoryMethodType The type of the lambda expression's represented method.
3282    * @param lambdaMethodType The type of the lambda expression's factory method.
3283    * @param targetMethodHandle A handle representing the target of the lambda expression's method.
3284    * @param specializedLambdaMethodType A specialization of the type of the lambda expression's represented method.
3285    * @param serializable {@code true} if the lambda expression should be serializable.
3286    * @param markerInterfaces A list of interfaces for the lambda expression to represent.
3287    * @param additionalBridges A list of additional bridge methods to be implemented by the lambda expression.
3288    * @param classFileTransformers A collection of class file transformers to apply when creating the class.
3289    * @return A binary representation of the transformed class file.
3290    */
 
3291  36 toggle public byte[] make(Object targetTypeLookup,
3292    String lambdaMethodName,
3293    Object factoryMethodType,
3294    Object lambdaMethodType,
3295    Object targetMethodHandle,
3296    Object specializedLambdaMethodType,
3297    boolean serializable,
3298    List<Class<?>> markerInterfaces,
3299    List<?> additionalBridges,
3300    Collection<? extends ClassFileTransformer> classFileTransformers) {
3301  36 JavaConstant.MethodType factoryMethod = JavaConstant.MethodType.ofLoaded(factoryMethodType);
3302  36 JavaConstant.MethodType lambdaMethod = JavaConstant.MethodType.ofLoaded(lambdaMethodType);
3303  36 JavaConstant.MethodHandle targetMethod = JavaConstant.MethodHandle.ofLoaded(targetMethodHandle, targetTypeLookup);
3304  36 JavaConstant.MethodType specializedLambdaMethod = JavaConstant.MethodType.ofLoaded(specializedLambdaMethodType);
3305  36 Class<?> targetType = JavaConstant.MethodHandle.lookupType(targetTypeLookup);
3306  36 String lambdaClassName = targetType.getName() + LAMBDA_TYPE_INFIX + LAMBDA_NAME_COUNTER.incrementAndGet();
3307  36 DynamicType.Builder<?> builder = byteBuddy
3308    .subclass(factoryMethod.getReturnType(), ConstructorStrategy.Default.NO_CONSTRUCTORS)
3309    .modifiers(TypeManifestation.FINAL, Visibility.PUBLIC)
3310    .implement(markerInterfaces)
3311    .name(lambdaClassName)
3312    .defineConstructor(Visibility.PUBLIC)
3313    .withParameters(factoryMethod.getParameterTypes())
3314    .intercept(ConstructorImplementation.INSTANCE)
3315    .method(named(lambdaMethodName)
3316    .and(takesArguments(lambdaMethod.getParameterTypes()))
3317    .and(returns(lambdaMethod.getReturnType())))
3318    .intercept(new LambdaMethodImplementation(targetMethod, specializedLambdaMethod));
3319  36 int index = 0;
3320  36 for (TypeDescription capturedType : factoryMethod.getParameterTypes()) {
3321  25 builder = builder.defineField(FIELD_PREFIX + ++index, capturedType, Visibility.PRIVATE, FieldManifestation.FINAL);
3322    }
3323  36 if (!factoryMethod.getParameterTypes().isEmpty()) {
3324  21 builder = builder.defineMethod(LAMBDA_FACTORY, factoryMethod.getReturnType(), Visibility.PRIVATE, Ownership.STATIC)
3325    .withParameters(factoryMethod.getParameterTypes())
3326    .intercept(FactoryImplementation.INSTANCE);
3327    }
3328  36 if (serializable) {
3329  5 if (!markerInterfaces.contains(Serializable.class)) {
3330  5 builder = builder.implement(Serializable.class);
3331    }
3332  5 builder = builder.defineMethod("writeReplace", Object.class, Visibility.PRIVATE)
3333    .intercept(new SerializationImplementation(new TypeDescription.ForLoadedType(targetType),
3334    factoryMethod.getReturnType(),
3335    lambdaMethodName,
3336    lambdaMethod,
3337    targetMethod,
3338    JavaConstant.MethodType.ofLoaded(specializedLambdaMethodType)));
3339  31 } else if (factoryMethod.getReturnType().isAssignableTo(Serializable.class)) {
3340  0 builder = builder.defineMethod("readObject", void.class, Visibility.PRIVATE)
3341    .withParameters(ObjectInputStream.class)
3342    .throwing(NotSerializableException.class)
3343    .intercept(ExceptionMethod.throwing(NotSerializableException.class, "Non-serializable lambda"))
3344    .defineMethod("writeObject", void.class, Visibility.PRIVATE)
3345    .withParameters(ObjectOutputStream.class)
3346    .throwing(NotSerializableException.class)
3347    .intercept(ExceptionMethod.throwing(NotSerializableException.class, "Non-serializable lambda"));
3348    }
3349  36 for (Object additionalBridgeType : additionalBridges) {
3350  0 JavaConstant.MethodType additionalBridge = JavaConstant.MethodType.ofLoaded(additionalBridgeType);
3351  0 builder = builder.defineMethod(lambdaMethodName, additionalBridge.getReturnType(), MethodManifestation.BRIDGE, Visibility.PUBLIC)
3352    .withParameters(additionalBridge.getParameterTypes())
3353    .intercept(new BridgeMethodImplementation(lambdaMethodName, lambdaMethod));
3354    }
3355  36 byte[] classFile = builder.make().getBytes();
3356  36 for (ClassFileTransformer classFileTransformer : classFileTransformers) {
3357  36 try {
3358  36 byte[] transformedClassFile = classFileTransformer.transform(targetType.getClassLoader(),
3359    lambdaClassName.replace('.', '/'),
3360    NOT_PREVIOUSLY_DEFINED,
3361    targetType.getProtectionDomain(),
3362    classFile);
3363  36 classFile = transformedClassFile == null
3364    ? classFile
3365    : transformedClassFile;
3366    } catch (Throwable ignored) {
3367    /* do nothing */
3368    }
3369    }
3370  36 return classFile;
3371    }
3372   
 
3373  5 toggle @Override
3374    public boolean equals(Object other) {
3375  5 return this == other || !(other == null || getClass() != other.getClass())
3376    && byteBuddy.equals(((LambdaInstanceFactory) other).byteBuddy);
3377    }
3378   
 
3379  3 toggle @Override
3380    public int hashCode() {
3381  3 return byteBuddy.hashCode();
3382    }
3383   
 
3384  3 toggle @Override
3385    public String toString() {
3386  3 return "AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory{" +
3387    "byteBuddy=" + byteBuddy +
3388    '}';
3389    }
3390   
3391    /**
3392    * Implements a lambda class's executing transformer.
3393    */
3394    @SuppressFBWarnings(value = "SE_BAD_FIELD", justification = "An enumeration does not serialize fields")
 
3395    protected enum ConstructorImplementation implements Implementation {
3396   
3397    /**
3398    * The singleton instance.
3399    */
3400    INSTANCE;
3401   
3402    /**
3403    * A reference to the {@link Object} class's default executing transformer.
3404    */
3405    private final MethodDescription.InDefinedShape objectConstructor;
3406   
3407    /**
3408    * Creates a new executing transformer implementation.
3409    */
 
3410  1 toggle ConstructorImplementation() {
3411  1 objectConstructor = TypeDescription.OBJECT.getDeclaredMethods().filter(isConstructor()).getOnly();
3412    }
3413   
 
3414  36 toggle @Override
3415    public ByteCodeAppender appender(Target implementationTarget) {
3416  36 return new Appender(implementationTarget.getInstrumentedType().getDeclaredFields());
3417    }
3418   
 
3419  36 toggle @Override
3420    public InstrumentedType prepare(InstrumentedType instrumentedType) {
3421  36 return instrumentedType;
3422    }
3423   
 
3424  1 toggle @Override
3425    public String toString() {
3426  1 return "AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.ConstructorImplementation." + name();
3427    }
3428   
3429    /**
3430    * An appender to implement the executing transformer.
3431    */
 
3432    protected static class Appender implements ByteCodeAppender {
3433   
3434    /**
3435    * The fields that are declared by the instrumented type.
3436    */
3437    private final List<FieldDescription.InDefinedShape> declaredFields;
3438   
3439    /**
3440    * Creates a new appender.
3441    *
3442    * @param declaredFields The fields that are declared by the instrumented type.
3443    */
 
3444  39 toggle protected Appender(List<FieldDescription.InDefinedShape> declaredFields) {
3445  39 this.declaredFields = declaredFields;
3446    }
3447   
 
3448  36 toggle @Override
3449    public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
3450  36 List<StackManipulation> fieldAssignments = new ArrayList<StackManipulation>(declaredFields.size() * 3);
3451  36 for (ParameterDescription parameterDescription : instrumentedMethod.getParameters()) {
3452  25 fieldAssignments.add(MethodVariableAccess.REFERENCE.loadOffset(0));
3453  25 fieldAssignments.add(MethodVariableAccess.of(parameterDescription.getType()).loadOffset(parameterDescription.getOffset()));
3454  25 fieldAssignments.add(FieldAccess.forField(declaredFields.get(parameterDescription.getIndex())).putter());
3455    }
3456  36 return new Size(new StackManipulation.Compound(
3457    MethodVariableAccess.REFERENCE.loadOffset(0),
3458    MethodInvocation.invoke(INSTANCE.objectConstructor),
3459    new StackManipulation.Compound(fieldAssignments),
3460    MethodReturn.VOID
3461    ).apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize());
3462    }
3463   
 
3464  5 toggle @Override
3465    public boolean equals(Object other) {
3466  5 return this == other || !(other == null || getClass() != other.getClass())
3467    && declaredFields.equals(((Appender) other).declaredFields);
3468    }
3469   
 
3470  3 toggle @Override
3471    public int hashCode() {
3472  3 return declaredFields.hashCode();
3473    }
3474   
 
3475  3 toggle @Override
3476    public String toString() {
3477  3 return "AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.ConstructorImplementation.Appender{" +
3478    "declaredFields=" + declaredFields +
3479    '}';
3480    }
3481    }
3482    }
3483   
3484    /**
3485    * An implementation of a instance factory for a lambda expression's class.
3486    */
 
3487    protected enum FactoryImplementation implements Implementation {
3488   
3489    /**
3490    * The singleton instance.
3491    */
3492    INSTANCE;
3493   
 
3494  21 toggle @Override
3495    public ByteCodeAppender appender(Target implementationTarget) {
3496  21 return new Appender(implementationTarget.getInstrumentedType());
3497    }
3498   
 
3499  21 toggle @Override
3500    public InstrumentedType prepare(InstrumentedType instrumentedType) {
3501  21 return instrumentedType;
3502    }
3503   
 
3504  1 toggle @Override
3505    public String toString() {
3506  1 return "AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.FactoryImplementation." + name();
3507    }
3508   
3509    /**
3510    * An appender for a lambda expression factory.
3511    */
 
3512    protected static class Appender implements ByteCodeAppender {
3513   
3514    /**
3515    * The instrumented type.
3516    */
3517    private final TypeDescription instrumentedType;
3518   
3519    /**
3520    * Creates a new appender.
3521    *
3522    * @param instrumentedType The instrumented type.
3523    */
 
3524  27 toggle protected Appender(TypeDescription instrumentedType) {
3525  27 this.instrumentedType = instrumentedType;
3526    }
3527   
 
3528  21 toggle @Override
3529    public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
3530  21 return new Size(new StackManipulation.Compound(
3531    TypeCreation.of(instrumentedType),
3532    Duplication.SINGLE,
3533    MethodVariableAccess.allArgumentsOf(instrumentedMethod),
3534    MethodInvocation.invoke(instrumentedType.getDeclaredMethods().filter(isConstructor()).getOnly()),
3535    MethodReturn.REFERENCE
3536    ).apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize());
3537    }
3538   
 
3539  10 toggle @Override
3540    public boolean equals(Object other) {
3541  10 return this == other || !(other == null || getClass() != other.getClass())
3542    && instrumentedType.equals(((Appender) other).instrumentedType);
3543    }
3544   
 
3545  6 toggle @Override
3546    public int hashCode() {
3547  6 return instrumentedType.hashCode();
3548    }
3549   
 
3550  6 toggle @Override
3551    public String toString() {
3552  6 return "AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.FactoryImplementation.Appender{" +
3553    "instrumentedType=" + instrumentedType +
3554    '}';
3555    }
3556    }
3557    }
3558   
3559    /**
3560    * Implements a lambda expression's functional method.
3561    */
 
3562    protected static class LambdaMethodImplementation implements Implementation {
3563   
3564    /**
3565    * The handle of the target method of the lambda expression.
3566    */
3567    private final JavaConstant.MethodHandle targetMethod;
3568   
3569    /**
3570    * The specialized type of the lambda method.
3571    */
3572    private final JavaConstant.MethodType specializedLambdaMethod;
3573   
3574    /**
3575    * Creates a implementation of a lambda expression's functional method.
3576    *
3577    * @param targetMethod The target method of the lambda expression.
3578    * @param specializedLambdaMethod The specialized type of the lambda method.
3579    */
 
3580  36 toggle protected LambdaMethodImplementation(JavaConstant.MethodHandle targetMethod, JavaConstant.MethodType specializedLambdaMethod) {
3581  36 this.targetMethod = targetMethod;
3582  36 this.specializedLambdaMethod = specializedLambdaMethod;
3583    }
3584   
 
3585  36 toggle @Override
3586    public ByteCodeAppender appender(Target implementationTarget) {
3587  36 return new Appender(targetMethod.getOwnerType()
3588    .getDeclaredMethods()
3589    .filter(named(targetMethod.getName())
3590    .and(returns(targetMethod.getReturnType()))
3591    .and(takesArguments(targetMethod.getParameterTypes())))
3592    .getOnly(),
3593    specializedLambdaMethod,
3594    implementationTarget.getInstrumentedType().getDeclaredFields());
3595    }
3596   
 
3597  36 toggle @Override
3598    public InstrumentedType prepare(InstrumentedType instrumentedType) {
3599  36 return instrumentedType;
3600    }
3601   
 
3602  0 toggle @Override
3603    public boolean equals(Object other) {
3604  0 if (this == other) return true;
3605  0 if (other == null || getClass() != other.getClass()) return false;
3606  0 LambdaMethodImplementation that = (LambdaMethodImplementation) other;
3607  0 return targetMethod.equals(that.targetMethod)
3608    && specializedLambdaMethod.equals(that.specializedLambdaMethod);
3609    }
3610   
 
3611  108 toggle @Override
3612    public int hashCode() {
3613  108 int result = targetMethod.hashCode();
3614  108 result = 31 * result + specializedLambdaMethod.hashCode();
3615  108 return result;
3616    }
3617   
 
3618  0 toggle @Override
3619    public String toString() {
3620  0 return "AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.LambdaMethodImplementation{" +
3621    "targetMethod=" + targetMethod +
3622    ", specializedLambdaMethod=" + specializedLambdaMethod +
3623    '}';
3624    }
3625   
3626    /**
3627    * An appender for a lambda expression's functional method.
3628    */
 
3629    protected static class Appender implements ByteCodeAppender {
3630   
3631    /**
3632    * The target method of the lambda expression.
3633    */
3634    private final MethodDescription targetMethod;
3635   
3636    /**
3637    * The specialized type of the lambda method.
3638    */
3639    private final JavaConstant.MethodType specializedLambdaMethod;
3640   
3641    /**
3642    * The instrumented type's declared fields.
3643    */
3644    private final List<FieldDescription.InDefinedShape> declaredFields;
3645   
3646    /**
3647    * Creates an appender of a lambda expression's functional method.
3648    *
3649    * @param targetMethod The target method of the lambda expression.
3650    * @param specializedLambdaMethod The specialized type of the lambda method.
3651    * @param declaredFields The instrumented type's declared fields.
3652    */
 
3653  41 toggle protected Appender(MethodDescription targetMethod,
3654    JavaConstant.MethodType specializedLambdaMethod,
3655    List<FieldDescription.InDefinedShape> declaredFields) {
3656  41 this.targetMethod = targetMethod;
3657  41 this.specializedLambdaMethod = specializedLambdaMethod;
3658  41 this.declaredFields = declaredFields;
3659    }
3660   
 
3661  36 toggle @Override
3662    public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
3663  36 List<StackManipulation> fieldAccess = new ArrayList<StackManipulation>(declaredFields.size() * 2);
3664  36 for (FieldDescription.InDefinedShape fieldDescription : declaredFields) {
3665  25 fieldAccess.add(MethodVariableAccess.REFERENCE.loadOffset(0));
3666  25 fieldAccess.add(FieldAccess.forField(fieldDescription).getter());
3667    }
3668  36 List<StackManipulation> parameterAccess = new ArrayList<StackManipulation>(instrumentedMethod.getParameters().size() * 2);
3669  36 for (ParameterDescription parameterDescription : instrumentedMethod.getParameters()) {
3670  11 parameterAccess.add(MethodVariableAccess.of(parameterDescription.getType()).loadOffset(parameterDescription.getOffset()));
3671  11 parameterAccess.add(Assigner.DEFAULT.assign(parameterDescription.getType(),
3672    specializedLambdaMethod.getParameterTypes().get(parameterDescription.getIndex()).asGenericType(),
3673    Assigner.Typing.DYNAMIC));
3674    }
3675  36 return new Size(new StackManipulation.Compound(
3676    new StackManipulation.Compound(fieldAccess),
3677    new StackManipulation.Compound(parameterAccess),
3678    MethodInvocation.invoke(targetMethod),
3679    MethodReturn.returning(targetMethod.getReturnType().asErasure())
3680    ).apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize());
3681    }
3682   
 
3683  7 toggle @Override
3684    public boolean equals(Object other) {
3685  1 if (this == other) return true;
3686  2 if (other == null || getClass() != other.getClass()) return false;
3687  4 Appender appender = (Appender) other;
3688  4 return targetMethod.equals(appender.targetMethod)
3689    && declaredFields.equals(appender.declaredFields)
3690    && specializedLambdaMethod.equals(appender.specializedLambdaMethod);
3691    }
3692   
 
3693  5 toggle @Override
3694    public int hashCode() {
3695  5 int result = targetMethod.hashCode();
3696  5 result = 31 * result + declaredFields.hashCode();
3697  5 result = 31 * result + specializedLambdaMethod.hashCode();
3698  5 return result;
3699    }
3700   
 
3701  5 toggle @Override
3702    public String toString() {
3703  5 return "AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.LambdaMethodImplementation.Appender{" +
3704    "targetMethod=" + targetMethod +
3705    ", specializedLambdaMethod=" + specializedLambdaMethod +
3706    ", declaredFields=" + declaredFields +
3707    '}';
3708    }
3709    }
3710    }
3711   
3712    /**
3713    * Implements the {@code writeReplace} method for serializable lambda expressions.
3714    */
 
3715    protected static class SerializationImplementation implements Implementation {
3716   
3717    /**
3718    * The lambda expression's declaring type.
3719    */
3720    private final TypeDescription targetType;
3721   
3722    /**
3723    * The lambda expression's functional type.
3724    */
3725    private final TypeDescription lambdaType;
3726   
3727    /**
3728    * The lambda expression's functional method name.
3729    */
3730    private final String lambdaMethodName;
3731   
3732    /**
3733    * The method type of the lambda expression's functional method.
3734    */
3735    private final JavaConstant.MethodType lambdaMethod;
3736   
3737    /**
3738    * A handle that references the lambda expressions invocation target.
3739    */
3740    private final JavaConstant.MethodHandle targetMethod;
3741   
3742    /**
3743    * The specialized method type of the lambda expression's functional method.
3744    */
3745    private final JavaConstant.MethodType specializedMethod;
3746   
3747    /**
3748    * Creates a new implementation for a serializable's lambda expression's {@code writeReplace} method.
3749    *
3750    * @param targetType The lambda expression's declaring type.
3751    * @param lambdaType The lambda expression's functional type.
3752    * @param lambdaMethodName The lambda expression's functional method name.
3753    * @param lambdaMethod The method type of the lambda expression's functional method.
3754    * @param targetMethod A handle that references the lambda expressions invocation target.
3755    * @param specializedMethod The specialized method type of the lambda expression's functional method.
3756    */
 
3757  13 toggle protected SerializationImplementation(TypeDescription targetType,
3758    TypeDescription lambdaType,
3759    String lambdaMethodName,
3760    JavaConstant.MethodType lambdaMethod,
3761    JavaConstant.MethodHandle targetMethod,
3762    JavaConstant.MethodType specializedMethod) {
3763  13 this.targetType = targetType;
3764  13 this.lambdaType = lambdaType;
3765  13 this.lambdaMethodName = lambdaMethodName;
3766  13 this.lambdaMethod = lambdaMethod;
3767  13 this.targetMethod = targetMethod;
3768  13 this.specializedMethod = specializedMethod;
3769    }
3770   
 
3771  5 toggle @Override
3772    public ByteCodeAppender appender(Target implementationTarget) {
3773  5 TypeDescription serializedLambda;
3774  5 try {
3775  5 serializedLambda = new TypeDescription.ForLoadedType(Class.forName("java.lang.invoke.SerializedLambda"));
3776    } catch (ClassNotFoundException exception) {
3777  0 throw new IllegalStateException("Cannot find class for lambda serialization", exception);
3778    }
3779  5 List<StackManipulation> lambdaArguments = new ArrayList<StackManipulation>(implementationTarget.getInstrumentedType().getDeclaredFields().size());
3780  5 for (FieldDescription.InDefinedShape fieldDescription : implementationTarget.getInstrumentedType().getDeclaredFields()) {
3781  5 lambdaArguments.add(new StackManipulation.Compound(MethodVariableAccess.REFERENCE.loadOffset(0),
3782    FieldAccess.forField(fieldDescription).getter(),
3783    Assigner.DEFAULT.assign(fieldDescription.getType(), TypeDescription.Generic.OBJECT, Assigner.Typing.STATIC)));
3784    }
3785  5 return new ByteCodeAppender.Simple(new StackManipulation.Compound(
3786    TypeCreation.of(serializedLambda),
3787    Duplication.SINGLE,
3788    ClassConstant.of(targetType),
3789    new TextConstant(lambdaType.getInternalName()),
3790    new TextConstant(lambdaMethodName),
3791    new TextConstant(lambdaMethod.getDescriptor()),
3792    IntegerConstant.forValue(targetMethod.getHandleType().getIdentifier()),
3793    new TextConstant(targetMethod.getOwnerType().getInternalName()),
3794    new TextConstant(targetMethod.getName()),
3795    new TextConstant(targetMethod.getDescriptor()),
3796    new TextConstant(specializedMethod.getDescriptor()),
3797    ArrayFactory.forType(TypeDescription.Generic.OBJECT).withValues(lambdaArguments),
3798    MethodInvocation.invoke(serializedLambda.getDeclaredMethods().filter(isConstructor()).getOnly()),
3799    MethodReturn.REFERENCE
3800    ));
3801    }
3802   
 
3803  5 toggle @Override
3804    public InstrumentedType prepare(InstrumentedType instrumentedType) {
3805  5 return instrumentedType;
3806    }
3807   
 
3808  10 toggle @Override
3809    public boolean equals(Object other) {
3810  1 if (this == other) return true;
3811  2 if (other == null || getClass() != other.getClass()) return false;
3812  7 SerializationImplementation that = (SerializationImplementation) other;
3813  7 return targetType.equals(that.targetType)
3814    && lambdaType.equals(that.lambdaType)
3815    && lambdaMethodName.equals(that.lambdaMethodName)
3816    && lambdaMethod.equals(that.lambdaMethod)
3817    && targetMethod.equals(that.targetMethod)
3818    && specializedMethod.equals(that.specializedMethod);
3819    }
3820   
 
3821  23 toggle @Override
3822    public int hashCode() {
3823  23 int result = targetType.hashCode();
3824  23 result = 31 * result + lambdaType.hashCode();
3825  23 result = 31 * result + lambdaMethodName.hashCode();
3826  23 result = 31 * result + lambdaMethod.hashCode();
3827  23 result = 31 * result + targetMethod.hashCode();
3828  23 result = 31 * result + specializedMethod.hashCode();
3829  23 return result;
3830    }
3831   
 
3832  8 toggle @Override
3833    public String toString() {
3834  8 return "AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.SerializationImplementation{" +
3835    "targetType=" + targetType +
3836    ", lambdaType=" + lambdaType +
3837    ", lambdaMethodName='" + lambdaMethodName + '\'' +
3838    ", lambdaMethod=" + lambdaMethod +
3839    ", targetMethod=" + targetMethod +
3840    ", specializedMethod=" + specializedMethod +
3841    '}';
3842    }
3843    }
3844   
3845    /**
3846    * Implements an explicit bridge method for a lambda expression.
3847    */
 
3848    protected static class BridgeMethodImplementation implements Implementation {
3849   
3850    /**
3851    * The name of the lambda expression's functional method.
3852    */
3853    private final String lambdaMethodName;
3854   
3855    /**
3856    * The actual type of the lambda expression's functional method.
3857    */
3858    private final JavaConstant.MethodType lambdaMethod;
3859   
3860    /**
3861    * Creates a new bridge method implementation for a lambda expression.
3862    *
3863    * @param lambdaMethodName The name of the lambda expression's functional method.
3864    * @param lambdaMethod The actual type of the lambda expression's functional method.
3865    */
 
3866  4 toggle protected BridgeMethodImplementation(String lambdaMethodName, JavaConstant.MethodType lambdaMethod) {
3867  4 this.lambdaMethodName = lambdaMethodName;
3868  4 this.lambdaMethod = lambdaMethod;
3869    }
3870   
 
3871  0 toggle @Override
3872    public ByteCodeAppender appender(Target implementationTarget) {
3873  0 return new Appender(implementationTarget.invokeSuper(new MethodDescription.SignatureToken(lambdaMethodName,
3874    lambdaMethod.getReturnType(),
3875    lambdaMethod.getParameterTypes())));
3876    }
3877   
 
3878  0 toggle @Override
3879    public InstrumentedType prepare(InstrumentedType instrumentedType) {
3880  0 return instrumentedType;
3881    }
3882   
 
3883  6 toggle @Override
3884    public boolean equals(Object other) {
3885  1 if (this == other) return true;
3886  2 if (other == null || getClass() != other.getClass()) return false;
3887  3 BridgeMethodImplementation that = (BridgeMethodImplementation) other;
3888  3 return lambdaMethodName.equals(that.lambdaMethodName) && lambdaMethod.equals(that.lambdaMethod);
3889    }
3890   
 
3891  4 toggle @Override
3892    public int hashCode() {
3893  4 int result = lambdaMethodName.hashCode();
3894  4 result = 31 * result + lambdaMethod.hashCode();
3895  4 return result;
3896    }
3897   
 
3898  4 toggle @Override
3899    public String toString() {
3900  4 return "AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.BridgeMethodImplementation{" +
3901    "lambdaMethodName='" + lambdaMethodName + '\'' +
3902    ", lambdaMethod=" + lambdaMethod +
3903    '}';
3904    }
3905   
3906    /**
3907    * An appender for implementing a bridge method for a lambda expression.
3908    */
 
3909    protected static class Appender implements ByteCodeAppender {
3910   
3911    /**
3912    * The invocation of the bridge's target method.
3913    */
3914    private final SpecialMethodInvocation bridgeTargetInvocation;
3915   
3916    /**
3917    * Creates a new appender for invoking a lambda expression's bridge method target.
3918    *
3919    * @param bridgeTargetInvocation The invocation of the bridge's target method.
3920    */
 
3921  3 toggle protected Appender(SpecialMethodInvocation bridgeTargetInvocation) {
3922  3 this.bridgeTargetInvocation = bridgeTargetInvocation;
3923    }
3924   
 
3925  0 toggle @Override
3926    public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
3927  0 return new Compound(new Simple(
3928    MethodVariableAccess.allArgumentsOf(instrumentedMethod)
3929    .asBridgeOf(bridgeTargetInvocation.getMethodDescription())
3930    .prependThisReference(),
3931    bridgeTargetInvocation,
3932  0 bridgeTargetInvocation.getMethodDescription().getReturnType().asErasure().isAssignableTo(instrumentedMethod.getReturnType().asErasure())
3933    ? StackManipulation.Trivial.INSTANCE
3934    : TypeCasting.to(instrumentedMethod.getReceiverType().asErasure()),
3935    MethodReturn.returning(instrumentedMethod.getReturnType().asErasure())
3936   
3937    )).apply(methodVisitor, implementationContext, instrumentedMethod);
3938    }
3939   
 
3940  5 toggle @Override
3941    public boolean equals(Object other) {
3942  5 return this == other || !(other == null || getClass() != other.getClass())
3943    && bridgeTargetInvocation.equals(((Appender) other).bridgeTargetInvocation);
3944    }
3945   
 
3946  3 toggle @Override
3947    public int hashCode() {
3948  3 return bridgeTargetInvocation.hashCode();
3949    }
3950   
 
3951  3 toggle @Override
3952    public String toString() {
3953  3 return "AgentBuilder.LambdaInstrumentationStrategy.LambdaInstanceFactory.BridgeMethodImplementation.Appender{" +
3954    "bridgeTargetInvocation=" + bridgeTargetInvocation +
3955    '}';
3956    }
3957    }
3958    }
3959    }
3960   
3961    /**
3962    * Implements the regular lambda meta factory. The implementation represents the following code:
3963    * <blockquote><pre>
3964    * public static CallSite metafactory(MethodHandles.Lookup caller,
3965    * String invokedName,
3966    * MethodType invokedType,
3967    * MethodType samMethodType,
3968    * MethodHandle implMethod,
3969    * MethodType instantiatedMethodType) throws Exception {
3970    * Unsafe unsafe = Unsafe.getUnsafe();
3971    * {@code Class<?>} lambdaClass = unsafe.defineAnonymousClass(caller.lookupClass(),
3972    * (byte[]) ClassLoader.getSystemClassLoader().loadClass("net.bytebuddy.agent.builder.LambdaFactory").getDeclaredMethod("make",
3973    * Object.class,
3974    * String.class,
3975    * Object.class,
3976    * Object.class,
3977    * Object.class,
3978    * Object.class,
3979    * boolean.class,
3980    * List.class,
3981    * List.class).invoke(null,
3982    * caller,
3983    * invokedName,
3984    * invokedType,
3985    * samMethodType,
3986    * implMethod,
3987    * instantiatedMethodType,
3988    * false,
3989    * Collections.emptyList(),
3990    * Collections.emptyList()),
3991    * null);
3992    * unsafe.ensureClassInitialized(lambdaClass);
3993    * return invokedType.parameterCount() == 0
3994    * ? new ConstantCallSite(MethodHandles.constant(invokedType.returnType(), lambdaClass.getDeclaredConstructors()[0].newInstance()))
3995    * : new ConstantCallSite(MethodHandles.Lookup.IMPL_LOOKUP.findStatic(lambdaClass, "get$Lambda", invokedType));
3996    * </pre></blockquote>
3997    */
 
3998    protected enum MetaFactoryRedirection implements AsmVisitorWrapper.ForDeclaredMethods.MethodVisitorWrapper {
3999   
4000    /**
4001    * The singleton instance.
4002    */
4003    INSTANCE;
4004   
 
4005  36 toggle @Override
4006    public MethodVisitor wrap(TypeDescription instrumentedType,
4007    MethodDescription.InDefinedShape methodDescription,
4008    MethodVisitor methodVisitor,
4009    ClassFileVersion classFileVersion,
4010    int writerFlags,
4011    int readerFlags) {
4012  36 methodVisitor.visitCode();
4013  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "sun/misc/Unsafe", "getUnsafe", "()Lsun/misc/Unsafe;", false);
4014  36 methodVisitor.visitVarInsn(Opcodes.ASTORE, 6);
4015  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 6);
4016  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
4017  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "lookupClass", "()Ljava/lang/Class;", false);
4018  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/ClassLoader", "getSystemClassLoader", "()Ljava/lang/ClassLoader;", false);
4019  36 methodVisitor.visitLdcInsn("net.bytebuddy.agent.builder.LambdaFactory");
4020  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/ClassLoader", "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", false);
4021  36 methodVisitor.visitLdcInsn("make");
4022  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 9);
4023  36 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class");
4024  36 methodVisitor.visitInsn(Opcodes.DUP);
4025  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4026  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
4027  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4028  36 methodVisitor.visitInsn(Opcodes.DUP);
4029  36 methodVisitor.visitInsn(Opcodes.ICONST_1);
4030  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/String;"));
4031  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4032  36 methodVisitor.visitInsn(Opcodes.DUP);
4033  36 methodVisitor.visitInsn(Opcodes.ICONST_2);
4034  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
4035  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4036  36 methodVisitor.visitInsn(Opcodes.DUP);
4037  36 methodVisitor.visitInsn(Opcodes.ICONST_3);
4038  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
4039  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4040  36 methodVisitor.visitInsn(Opcodes.DUP);
4041  36 methodVisitor.visitInsn(Opcodes.ICONST_4);
4042  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
4043  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4044  36 methodVisitor.visitInsn(Opcodes.DUP);
4045  36 methodVisitor.visitInsn(Opcodes.ICONST_5);
4046  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
4047  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4048  36 methodVisitor.visitInsn(Opcodes.DUP);
4049  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 6);
4050  36 methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
4051  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4052  36 methodVisitor.visitInsn(Opcodes.DUP);
4053  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 7);
4054  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/util/List;"));
4055  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4056  36 methodVisitor.visitInsn(Opcodes.DUP);
4057  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 8);
4058  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/util/List;"));
4059  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4060  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getDeclaredMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false);
4061  36 methodVisitor.visitInsn(Opcodes.ACONST_NULL);
4062  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 9);
4063  36 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
4064  36 methodVisitor.visitInsn(Opcodes.DUP);
4065  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4066  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
4067  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4068  36 methodVisitor.visitInsn(Opcodes.DUP);
4069  36 methodVisitor.visitInsn(Opcodes.ICONST_1);
4070  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
4071  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4072  36 methodVisitor.visitInsn(Opcodes.DUP);
4073  36 methodVisitor.visitInsn(Opcodes.ICONST_2);
4074  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 2);
4075  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4076  36 methodVisitor.visitInsn(Opcodes.DUP);
4077  36 methodVisitor.visitInsn(Opcodes.ICONST_3);
4078  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 3);
4079  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4080  36 methodVisitor.visitInsn(Opcodes.DUP);
4081  36 methodVisitor.visitInsn(Opcodes.ICONST_4);
4082  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 4);
4083  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4084  36 methodVisitor.visitInsn(Opcodes.DUP);
4085  36 methodVisitor.visitInsn(Opcodes.ICONST_5);
4086  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 5);
4087  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4088  36 methodVisitor.visitInsn(Opcodes.DUP);
4089  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 6);
4090  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4091  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
4092  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4093  36 methodVisitor.visitInsn(Opcodes.DUP);
4094  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 7);
4095  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/Collections", "emptyList", "()Ljava/util/List;", false);
4096  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4097  36 methodVisitor.visitInsn(Opcodes.DUP);
4098  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 8);
4099  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/Collections", "emptyList", "()Ljava/util/List;", false);
4100  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4101  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false);
4102  36 methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, "[B");
4103  36 methodVisitor.visitInsn(Opcodes.ACONST_NULL);
4104  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "sun/misc/Unsafe", "defineAnonymousClass", "(Ljava/lang/Class;[B[Ljava/lang/Object;)Ljava/lang/Class;", false);
4105  36 methodVisitor.visitVarInsn(Opcodes.ASTORE, 7);
4106  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 6);
4107  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 7);
4108  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "sun/misc/Unsafe", "ensureClassInitialized", "(Ljava/lang/Class;)V", false);
4109  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 2);
4110  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/invoke/MethodType", "parameterCount", "()I", false);
4111  36 Label conditionalDefault = new Label();
4112  36 methodVisitor.visitJumpInsn(Opcodes.IFNE, conditionalDefault);
4113  36 methodVisitor.visitTypeInsn(Opcodes.NEW, "java/lang/invoke/ConstantCallSite");
4114  36 methodVisitor.visitInsn(Opcodes.DUP);
4115  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 2);
4116  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/invoke/MethodType", "returnType", "()Ljava/lang/Class;", false);
4117  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 7);
4118  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getDeclaredConstructors", "()[Ljava/lang/reflect/Constructor;", false);
4119  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4120  36 methodVisitor.visitInsn(Opcodes.AALOAD);
4121  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4122  36 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
4123  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Constructor", "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;", false);
4124  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/invoke/MethodHandles", "constant", "(Ljava/lang/Class;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;", false);
4125  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/invoke/ConstantCallSite", "<init>", "(Ljava/lang/invoke/MethodHandle;)V", false);
4126  36 Label conditionalAlternative = new Label();
4127  36 methodVisitor.visitJumpInsn(Opcodes.GOTO, conditionalAlternative);
4128  36 methodVisitor.visitLabel(conditionalDefault);
4129  36 methodVisitor.visitFrame(Opcodes.F_APPEND, 2, new Object[]{"sun/misc/Unsafe", "java/lang/Class"}, 0, null);
4130  36 methodVisitor.visitTypeInsn(Opcodes.NEW, "java/lang/invoke/ConstantCallSite");
4131  36 methodVisitor.visitInsn(Opcodes.DUP);
4132  36 methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/invoke/MethodHandles$Lookup", "IMPL_LOOKUP", "Ljava/lang/invoke/MethodHandles$Lookup;");
4133  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 7);
4134  36 methodVisitor.visitLdcInsn("get$Lambda");
4135  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 2);
4136  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "findStatic", "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;", false);
4137  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/invoke/ConstantCallSite", "<init>", "(Ljava/lang/invoke/MethodHandle;)V", false);
4138  36 methodVisitor.visitLabel(conditionalAlternative);
4139  36 methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/invoke/CallSite"});
4140  36 methodVisitor.visitInsn(Opcodes.ARETURN);
4141  36 methodVisitor.visitMaxs(8, 8);
4142  36 methodVisitor.visitEnd();
4143  36 return IGNORE_ORIGINAL;
4144    }
4145   
 
4146  1 toggle @Override
4147    public String toString() {
4148  1 return "AgentBuilder.LambdaInstrumentationStrategy.MetaFactoryRedirection." + name();
4149    }
4150    }
4151   
4152    /**
4153    * Implements the alternative lambda meta factory. The implementation represents the following code:
4154    * <blockquote><pre>
4155    * public static CallSite altMetafactory(MethodHandles.Lookup caller,
4156    * String invokedName,
4157    * MethodType invokedType,
4158    * Object... args) throws Exception {
4159    * int flags = (Integer) args[3];
4160    * int argIndex = 4;
4161    * {@code Class<?>[]} markerInterface;
4162    * if ((flags {@code &} FLAG_MARKERS) != 0) {
4163    * int markerCount = (Integer) args[argIndex++];
4164    * markerInterface = new {@code Class<?>}[markerCount];
4165    * System.arraycopy(args, argIndex, markerInterface, 0, markerCount);
4166    * argIndex += markerCount;
4167    * } else {
4168    * markerInterface = new {@code Class<?>}[0];
4169    * }
4170    * MethodType[] additionalBridge;
4171    * if ((flags {@code &} FLAG_BRIDGES) != 0) {
4172    * int bridgeCount = (Integer) args[argIndex++];
4173    * additionalBridge = new MethodType[bridgeCount];
4174    * System.arraycopy(args, argIndex, additionalBridge, 0, bridgeCount);
4175    * // argIndex += bridgeCount;
4176    * } else {
4177    * additionalBridge = new MethodType[0];
4178    * }
4179    * Unsafe unsafe = Unsafe.getUnsafe();
4180    * {@code Class<?>} lambdaClass = unsafe.defineAnonymousClass(caller.lookupClass(),
4181    * (byte[]) ClassLoader.getSystemClassLoader().loadClass("net.bytebuddy.agent.builder.LambdaFactory").getDeclaredMethod("make",
4182    * Object.class,
4183    * String.class,
4184    * Object.class,
4185    * Object.class,
4186    * Object.class,
4187    * Object.class,
4188    * boolean.class,
4189    * List.class,
4190    * List.class).invoke(null,
4191    * caller,
4192    * invokedName,
4193    * invokedType,
4194    * args[0],
4195    * args[1],
4196    * args[2],
4197    * (flags {@code &} FLAG_SERIALIZABLE) != 0,
4198    * Arrays.asList(markerInterface),
4199    * Arrays.asList(additionalBridge)),
4200    * null);
4201    * unsafe.ensureClassInitialized(lambdaClass);
4202    * return invokedType.parameterCount() == 0
4203    * ? new ConstantCallSite(MethodHandles.constant(invokedType.returnType(), lambdaClass.getDeclaredConstructors()[0].newInstance()))
4204    * : new ConstantCallSite(MethodHandles.Lookup.IMPL_LOOKUP.findStatic(lambdaClass, "get$Lambda", invokedType));
4205    * }
4206    * </pre></blockquote>
4207    */
 
4208    protected enum AlternativeMetaFactoryRedirection implements AsmVisitorWrapper.ForDeclaredMethods.MethodVisitorWrapper {
4209   
4210    /**
4211    * The singleton instance.
4212    */
4213    INSTANCE;
4214   
 
4215  36 toggle @Override
4216    public MethodVisitor wrap(TypeDescription instrumentedType,
4217    MethodDescription.InDefinedShape methodDescription,
4218    MethodVisitor methodVisitor,
4219    ClassFileVersion classFileVersion,
4220    int writerFlags,
4221    int readerFlags) {
4222  36 methodVisitor.visitCode();
4223  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 3);
4224  36 methodVisitor.visitInsn(Opcodes.ICONST_3);
4225  36 methodVisitor.visitInsn(Opcodes.AALOAD);
4226  36 methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Integer");
4227  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
4228  36 methodVisitor.visitVarInsn(Opcodes.ISTORE, 4);
4229  36 methodVisitor.visitInsn(Opcodes.ICONST_4);
4230  36 methodVisitor.visitVarInsn(Opcodes.ISTORE, 5);
4231  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 4);
4232  36 methodVisitor.visitInsn(Opcodes.ICONST_2);
4233  36 methodVisitor.visitInsn(Opcodes.IAND);
4234  36 Label markerInterfaceLoop = new Label();
4235  36 methodVisitor.visitJumpInsn(Opcodes.IFEQ, markerInterfaceLoop);
4236  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 3);
4237  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 5);
4238  36 methodVisitor.visitIincInsn(5, 1);
4239  36 methodVisitor.visitInsn(Opcodes.AALOAD);
4240  36 methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Integer");
4241  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
4242  36 methodVisitor.visitVarInsn(Opcodes.ISTORE, 7);
4243  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 7);
4244  36 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class");
4245  36 methodVisitor.visitVarInsn(Opcodes.ASTORE, 6);
4246  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 3);
4247  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 5);
4248  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 6);
4249  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4250  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 7);
4251  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", false);
4252  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 5);
4253  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 7);
4254  36 methodVisitor.visitInsn(Opcodes.IADD);
4255  36 methodVisitor.visitVarInsn(Opcodes.ISTORE, 5);
4256  36 Label markerInterfaceExit = new Label();
4257  36 methodVisitor.visitJumpInsn(Opcodes.GOTO, markerInterfaceExit);
4258  36 methodVisitor.visitLabel(markerInterfaceLoop);
4259  36 methodVisitor.visitFrame(Opcodes.F_APPEND, 2, new Object[]{Opcodes.INTEGER, Opcodes.INTEGER}, 0, null);
4260  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4261  36 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class");
4262  36 methodVisitor.visitVarInsn(Opcodes.ASTORE, 6);
4263  36 methodVisitor.visitLabel(markerInterfaceExit);
4264  36 methodVisitor.visitFrame(Opcodes.F_APPEND, 1, new Object[]{"[Ljava/lang/Class;"}, 0, null);
4265  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 4);
4266  36 methodVisitor.visitInsn(Opcodes.ICONST_4);
4267  36 methodVisitor.visitInsn(Opcodes.IAND);
4268  36 Label additionalBridgesLoop = new Label();
4269  36 methodVisitor.visitJumpInsn(Opcodes.IFEQ, additionalBridgesLoop);
4270  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 3);
4271  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 5);
4272  36 methodVisitor.visitIincInsn(5, 1);
4273  36 methodVisitor.visitInsn(Opcodes.AALOAD);
4274  36 methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Integer");
4275  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
4276  36 methodVisitor.visitVarInsn(Opcodes.ISTORE, 8);
4277  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 8);
4278  36 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/invoke/MethodType");
4279  36 methodVisitor.visitVarInsn(Opcodes.ASTORE, 7);
4280  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 3);
4281  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 5);
4282  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 7);
4283  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4284  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 8);
4285  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", false);
4286  36 Label additionalBridgesExit = new Label();
4287  36 methodVisitor.visitJumpInsn(Opcodes.GOTO, additionalBridgesExit);
4288  36 methodVisitor.visitLabel(additionalBridgesLoop);
4289  36 methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
4290  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4291  36 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/invoke/MethodType");
4292  36 methodVisitor.visitVarInsn(Opcodes.ASTORE, 7);
4293  36 methodVisitor.visitLabel(additionalBridgesExit);
4294  36 methodVisitor.visitFrame(Opcodes.F_APPEND, 1, new Object[]{"[Ljava/lang/invoke/MethodType;"}, 0, null);
4295  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "sun/misc/Unsafe", "getUnsafe", "()Lsun/misc/Unsafe;", false);
4296  36 methodVisitor.visitVarInsn(Opcodes.ASTORE, 8);
4297  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 8);
4298  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
4299  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "lookupClass", "()Ljava/lang/Class;", false);
4300  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/ClassLoader", "getSystemClassLoader", "()Ljava/lang/ClassLoader;", false);
4301  36 methodVisitor.visitLdcInsn("net.bytebuddy.agent.builder.LambdaFactory");
4302  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/ClassLoader", "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", false);
4303  36 methodVisitor.visitLdcInsn("make");
4304  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 9);
4305  36 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class");
4306  36 methodVisitor.visitInsn(Opcodes.DUP);
4307  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4308  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
4309  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4310  36 methodVisitor.visitInsn(Opcodes.DUP);
4311  36 methodVisitor.visitInsn(Opcodes.ICONST_1);
4312  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/String;"));
4313  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4314  36 methodVisitor.visitInsn(Opcodes.DUP);
4315  36 methodVisitor.visitInsn(Opcodes.ICONST_2);
4316  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
4317  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4318  36 methodVisitor.visitInsn(Opcodes.DUP);
4319  36 methodVisitor.visitInsn(Opcodes.ICONST_3);
4320  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
4321  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4322  36 methodVisitor.visitInsn(Opcodes.DUP);
4323  36 methodVisitor.visitInsn(Opcodes.ICONST_4);
4324  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
4325  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4326  36 methodVisitor.visitInsn(Opcodes.DUP);
4327  36 methodVisitor.visitInsn(Opcodes.ICONST_5);
4328  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
4329  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4330  36 methodVisitor.visitInsn(Opcodes.DUP);
4331  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 6);
4332  36 methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
4333  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4334  36 methodVisitor.visitInsn(Opcodes.DUP);
4335  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 7);
4336  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/util/List;"));
4337  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4338  36 methodVisitor.visitInsn(Opcodes.DUP);
4339  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 8);
4340  36 methodVisitor.visitLdcInsn(Type.getType("Ljava/util/List;"));
4341  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4342  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getDeclaredMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false);
4343  36 methodVisitor.visitInsn(Opcodes.ACONST_NULL);
4344  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 9);
4345  36 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
4346  36 methodVisitor.visitInsn(Opcodes.DUP);
4347  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4348  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
4349  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4350  36 methodVisitor.visitInsn(Opcodes.DUP);
4351  36 methodVisitor.visitInsn(Opcodes.ICONST_1);
4352  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
4353  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4354  36 methodVisitor.visitInsn(Opcodes.DUP);
4355  36 methodVisitor.visitInsn(Opcodes.ICONST_2);
4356  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 2);
4357  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4358  36 methodVisitor.visitInsn(Opcodes.DUP);
4359  36 methodVisitor.visitInsn(Opcodes.ICONST_3);
4360  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 3);
4361  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4362  36 methodVisitor.visitInsn(Opcodes.AALOAD);
4363  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4364  36 methodVisitor.visitInsn(Opcodes.DUP);
4365  36 methodVisitor.visitInsn(Opcodes.ICONST_4);
4366  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 3);
4367  36 methodVisitor.visitInsn(Opcodes.ICONST_1);
4368  36 methodVisitor.visitInsn(Opcodes.AALOAD);
4369  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4370  36 methodVisitor.visitInsn(Opcodes.DUP);
4371  36 methodVisitor.visitInsn(Opcodes.ICONST_5);
4372  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 3);
4373  36 methodVisitor.visitInsn(Opcodes.ICONST_2);
4374  36 methodVisitor.visitInsn(Opcodes.AALOAD);
4375  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4376  36 methodVisitor.visitInsn(Opcodes.DUP);
4377  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 6);
4378  36 methodVisitor.visitVarInsn(Opcodes.ILOAD, 4);
4379  36 methodVisitor.visitInsn(Opcodes.ICONST_1);
4380  36 methodVisitor.visitInsn(Opcodes.IAND);
4381  36 Label callSiteConditional = new Label();
4382  36 methodVisitor.visitJumpInsn(Opcodes.IFEQ, callSiteConditional);
4383  36 methodVisitor.visitInsn(Opcodes.ICONST_1);
4384  36 Label callSiteAlternative = new Label();
4385  36 methodVisitor.visitJumpInsn(Opcodes.GOTO, callSiteAlternative);
4386  36 methodVisitor.visitLabel(callSiteConditional);
4387  36 methodVisitor.visitFrame(Opcodes.F_FULL, 9, new Object[]{"java/lang/invoke/MethodHandles$Lookup", "java/lang/String", "java/lang/invoke/MethodType", "[Ljava/lang/Object;", Opcodes.INTEGER, Opcodes.INTEGER, "[Ljava/lang/Class;", "[Ljava/lang/invoke/MethodType;", "sun/misc/Unsafe"}, 7, new Object[]{"sun/misc/Unsafe", "java/lang/Class", "java/lang/reflect/Method", Opcodes.NULL, "[Ljava/lang/Object;", "[Ljava/lang/Object;", Opcodes.INTEGER});
4388  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4389  36 methodVisitor.visitLabel(callSiteAlternative);
4390  36 methodVisitor.visitFrame(Opcodes.F_FULL, 9, new Object[]{"java/lang/invoke/MethodHandles$Lookup", "java/lang/String", "java/lang/invoke/MethodType", "[Ljava/lang/Object;", Opcodes.INTEGER, Opcodes.INTEGER, "[Ljava/lang/Class;", "[Ljava/lang/invoke/MethodType;", "sun/misc/Unsafe"}, 8, new Object[]{"sun/misc/Unsafe", "java/lang/Class", "java/lang/reflect/Method", Opcodes.NULL, "[Ljava/lang/Object;", "[Ljava/lang/Object;", Opcodes.INTEGER, Opcodes.INTEGER});
4391  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
4392  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4393  36 methodVisitor.visitInsn(Opcodes.DUP);
4394  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 7);
4395  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 6);
4396  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/Arrays", "asList", "([Ljava/lang/Object;)Ljava/util/List;", false);
4397  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4398  36 methodVisitor.visitInsn(Opcodes.DUP);
4399  36 methodVisitor.visitIntInsn(Opcodes.BIPUSH, 8);
4400  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 7);
4401  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/Arrays", "asList", "([Ljava/lang/Object;)Ljava/util/List;", false);
4402  36 methodVisitor.visitInsn(Opcodes.AASTORE);
4403  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Method", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", false);
4404  36 methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, "[B");
4405  36 methodVisitor.visitInsn(Opcodes.ACONST_NULL);
4406  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "sun/misc/Unsafe", "defineAnonymousClass", "(Ljava/lang/Class;[B[Ljava/lang/Object;)Ljava/lang/Class;", false);
4407  36 methodVisitor.visitVarInsn(Opcodes.ASTORE, 9);
4408  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 8);
4409  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 9);
4410  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "sun/misc/Unsafe", "ensureClassInitialized", "(Ljava/lang/Class;)V", false);
4411  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 2);
4412  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/invoke/MethodType", "parameterCount", "()I", false);
4413  36 Label callSiteJump = new Label();
4414  36 methodVisitor.visitJumpInsn(Opcodes.IFNE, callSiteJump);
4415  36 methodVisitor.visitTypeInsn(Opcodes.NEW, "java/lang/invoke/ConstantCallSite");
4416  36 methodVisitor.visitInsn(Opcodes.DUP);
4417  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 2);
4418  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/invoke/MethodType", "returnType", "()Ljava/lang/Class;", false);
4419  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 9);
4420  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getDeclaredConstructors", "()[Ljava/lang/reflect/Constructor;", false);
4421  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4422  36 methodVisitor.visitInsn(Opcodes.AALOAD);
4423  36 methodVisitor.visitInsn(Opcodes.ICONST_0);
4424  36 methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
4425  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Constructor", "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;", false);
4426  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/invoke/MethodHandles", "constant", "(Ljava/lang/Class;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;", false);
4427  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/invoke/ConstantCallSite", "<init>", "(Ljava/lang/invoke/MethodHandle;)V", false);
4428  36 Label callSiteExit = new Label();
4429  36 methodVisitor.visitJumpInsn(Opcodes.GOTO, callSiteExit);
4430  36 methodVisitor.visitLabel(callSiteJump);
4431  36 methodVisitor.visitFrame(Opcodes.F_APPEND, 1, new Object[]{"java/lang/Class"}, 0, null);
4432  36 methodVisitor.visitTypeInsn(Opcodes.NEW, "java/lang/invoke/ConstantCallSite");
4433  36 methodVisitor.visitInsn(Opcodes.DUP);
4434  36 methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/invoke/MethodHandles$Lookup", "IMPL_LOOKUP", "Ljava/lang/invoke/MethodHandles$Lookup;");
4435  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 9);
4436  36 methodVisitor.visitLdcInsn("get$Lambda");
4437  36 methodVisitor.visitVarInsn(Opcodes.ALOAD, 2);
4438  36 methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "findStatic", "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;", false);
4439  36 methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/invoke/ConstantCallSite", "<init>", "(Ljava/lang/invoke/MethodHandle;)V", false);
4440  36 methodVisitor.visitLabel(callSiteExit);
4441  36 methodVisitor.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/invoke/CallSite"});
4442  36 methodVisitor.visitInsn(Opcodes.ARETURN);
4443  36 methodVisitor.visitMaxs(9, 10);
4444  36 methodVisitor.visitEnd();
4445  36 return IGNORE_ORIGINAL;
4446    }
4447   
 
4448  1 toggle @Override
4449    public String toString() {
4450  1 return "AgentBuilder.LambdaInstrumentationStrategy.AlternativeMetaFactoryRedirection." + name();
4451    }
4452    }
4453    }
4454   
4455    /**
4456    * <p>
4457    * The default implementation of an {@link net.bytebuddy.agent.builder.AgentBuilder}.
4458    * </p>
4459    * <p>
4460    * By default, Byte Buddy ignores any types loaded by the bootstrap class loader and
4461    * any synthetic type. Self-injection and rebasing is enabled. In order to avoid class format changes, set
4462    * {@link AgentBuilder#disableBootstrapInjection()}). All types are parsed without their debugging information ({@link TypeLocator.Default#FAST}).
4463    * </p>
4464    */
 
4465    class Default implements AgentBuilder {
4466   
4467    /**
4468    * The name of the Byte Buddy {@code net.bytebuddy.agent.Installer} class.
4469    */
4470    private static final String INSTALLER_TYPE = "net.bytebuddy.agent.Installer";
4471   
4472    /**
4473    * The name of the {@code net.bytebuddy.agent.Installer} field containing an installed {@link Instrumentation}.
4474    */
4475    private static final String INSTRUMENTATION_FIELD = "instrumentation";
4476   
4477    /**
4478    * Indicator for access to a static member via reflection to make the code more readable.
4479    */
4480    private static final Object STATIC_FIELD = null;
4481   
4482    /**
4483    * The value that is to be returned from a {@link java.lang.instrument.ClassFileTransformer} to indicate
4484    * that no class file transformation is to be applied.
4485    */
4486    private static final byte[] NO_TRANSFORMATION = null;
4487   
4488    /**
4489    * The {@link net.bytebuddy.ByteBuddy} instance to be used.
4490    */
4491    private final ByteBuddy byteBuddy;
4492   
4493    /**
4494    * The type locator to use.
4495    */
4496    private final TypeLocator typeLocator;
4497   
4498    /**
4499    * The definition handler to use.
4500    */
4501    private final TypeStrategy typeStrategy;
4502   
4503    /**
4504    * The listener to notify on transformations.
4505    */
4506    private final Listener listener;
4507   
4508    /**
4509    * The native method strategy to use.
4510    */
4511    private final NativeMethodStrategy nativeMethodStrategy;
4512   
4513    /**
4514    * The access control context to use for loading classes.
4515    */
4516    private final AccessControlContext accessControlContext;
4517   
4518    /**
4519    * The initialization strategy to use for creating classes.
4520    */
4521    private final InitializationStrategy initializationStrategy;
4522   
4523    /**
4524    * The redefinition strategy to apply.
4525    */
4526    private final RedefinitionStrategy redefinitionStrategy;
4527   
4528    /**
4529    * The injection strategy for injecting classes into the bootstrap class loader.
4530    */
4531    private final BootstrapInjectionStrategy bootstrapInjectionStrategy;
4532   
4533    /**
4534    * A strategy to determine of the {@code LambdaMetfactory} should be instrumented to allow for the instrumentation
4535    * of classes that represent lambda expressions.
4536    */
4537    private final LambdaInstrumentationStrategy lambdaInstrumentationStrategy;
4538   
4539    /**
4540    * The description strategy for resolving type descriptions for types.
4541    */
4542    private final DescriptionStrategy descriptionStrategy;
4543   
4544    /**
4545    * The installation strategy to use.
4546    */
4547    private final InstallationStrategy installationStrategy;
4548   
4549    /**
4550    * Identifies types that should not be instrumented.
4551    */
4552    private final RawMatcher ignoredTypeMatcher;
4553   
4554    /**
4555    * The transformation object for handling type transformations.
4556    */
4557    private final Transformation transformation;
4558   
4559    /**
4560    * Creates a new default agent builder that uses a default {@link net.bytebuddy.ByteBuddy} instance for creating classes.
4561    *
4562    * @see Default#Default(ByteBuddy)
4563    */
 
4564  120 toggle public Default() {
4565  120 this(new ByteBuddy());
4566    }
4567   
4568    /**
4569    * Creates a new agent builder with default settings. By default, Byte Buddy ignores any types loaded by the bootstrap class loader, any
4570    * type within a {@code net.bytebuddy} package and any synthetic type. Self-injection and rebasing is enabled. In order to avoid class format
4571    * changes, set {@link AgentBuilder#disableBootstrapInjection()}). All types are parsed without their debugging information
4572    * ({@link TypeLocator.Default#FAST}).
4573    *
4574    * @param byteBuddy The Byte Buddy instance to be used.
4575    */
 
4576  157 toggle public Default(ByteBuddy byteBuddy) {
4577  157 this(byteBuddy,
4578    TypeLocator.Default.FAST,
4579    TypeStrategy.Default.REBASE,
4580    Listener.NoOp.INSTANCE,
4581    NativeMethodStrategy.Disabled.INSTANCE,
4582    AccessController.getContext(),
4583    InitializationStrategy.SelfInjection.SPLIT,
4584    RedefinitionStrategy.DISABLED,
4585    BootstrapInjectionStrategy.Disabled.INSTANCE,
4586    LambdaInstrumentationStrategy.DISABLED,
4587    DescriptionStrategy.Default.HYBRID,
4588    InstallationStrategy.Default.ESCALATING,
4589    new RawMatcher.Disjunction(new RawMatcher.ForElementMatchers(any(), isBootstrapClassLoader(), any()), new RawMatcher.ForElementMatchers(nameStartsWith("net.bytebuddy.").<TypeDescription>or(isSynthetic()), any(), any())),
4590    Transformation.Ignored.INSTANCE);
4591    }
4592   
4593    /**
4594    * Creates a new default agent builder.
4595    *
4596    * @param byteBuddy The Byte Buddy instance to be used.
4597    * @param typeLocator The type locator to use.
4598    * @param typeStrategy The definition handler to use.
4599    * @param listener The listener to notify on transformations.
4600    * @param nativeMethodStrategy The native method strategy to apply.
4601    * @param accessControlContext The access control context to use for loading classes.
4602    * @param initializationStrategy The initialization strategy to use for transformed types.
4603    * @param redefinitionStrategy The redefinition strategy to apply.
4604    * @param bootstrapInjectionStrategy The injection strategy for injecting classes into the bootstrap class loader.
4605    * @param lambdaInstrumentationStrategy A strategy to determine of the {@code LambdaMetfactory} should be instrumented to allow for the
4606    * instrumentation of classes that represent lambda expressions.
4607    * @param descriptionStrategy The description strategy for resolving type descriptions for types.
4608    * @param installationStrategy The installation strategy to use.
4609    * @param ignoredTypeMatcher Identifies types that should not be instrumented.
4610    * @param transformation The transformation object for handling type transformations.
4611    */
 
4612  1001 toggle protected Default(ByteBuddy byteBuddy,
4613    TypeLocator typeLocator,
4614    TypeStrategy typeStrategy,
4615    Listener listener,
4616    NativeMethodStrategy nativeMethodStrategy,
4617    AccessControlContext accessControlContext,
4618    InitializationStrategy initializationStrategy,
4619    RedefinitionStrategy redefinitionStrategy,
4620    BootstrapInjectionStrategy bootstrapInjectionStrategy,
4621    LambdaInstrumentationStrategy lambdaInstrumentationStrategy,
4622    DescriptionStrategy descriptionStrategy,
4623    InstallationStrategy installationStrategy,
4624    RawMatcher ignoredTypeMatcher,
4625    Transformation transformation) {
4626  1001 this.byteBuddy = byteBuddy;
4627  1001 this.typeLocator = typeLocator;
4628  1001 this.typeStrategy = typeStrategy;
4629  1001 this.listener = listener;
4630  1001 this.nativeMethodStrategy = nativeMethodStrategy;
4631  1001 this.accessControlContext = accessControlContext;
4632  1001 this.initializationStrategy = initializationStrategy;
4633  1001 this.redefinitionStrategy = redefinitionStrategy;
4634  1001 this.bootstrapInjectionStrategy = bootstrapInjectionStrategy;
4635  1001 this.lambdaInstrumentationStrategy = lambdaInstrumentationStrategy;
4636  1001 this.descriptionStrategy = descriptionStrategy;
4637  1001 this.installationStrategy = installationStrategy;
4638  1001 this.ignoredTypeMatcher = ignoredTypeMatcher;
4639  1001 this.transformation = transformation;
4640    }
4641   
 
4642  0 toggle @Override
4643    public AgentBuilder with(ByteBuddy byteBuddy) {
4644  0 return new Default(byteBuddy,
4645    typeLocator,
4646    typeStrategy,
4647    listener,
4648    nativeMethodStrategy,
4649    accessControlContext,
4650    initializationStrategy,
4651    redefinitionStrategy,
4652    bootstrapInjectionStrategy,
4653    lambdaInstrumentationStrategy,
4654    descriptionStrategy,
4655    installationStrategy,
4656    ignoredTypeMatcher,
4657    transformation);
4658    }
4659   
 
4660  32 toggle @Override
4661    public AgentBuilder with(Listener listener) {
4662  32 return new Default(byteBuddy,
4663    typeLocator,
4664    typeStrategy,
4665    new Listener.Compound(this.listener, listener),
4666    nativeMethodStrategy,
4667    accessControlContext,
4668    initializationStrategy,
4669    redefinitionStrategy,
4670    bootstrapInjectionStrategy,
4671    lambdaInstrumentationStrategy,
4672    descriptionStrategy,
4673    installationStrategy,
4674    ignoredTypeMatcher,
4675    transformation);
4676    }
4677   
 
4678  73 toggle @Override
4679    public AgentBuilder with(TypeStrategy typeStrategy) {
4680  73 return new Default(byteBuddy,
4681    typeLocator,
4682    typeStrategy,
4683    listener,
4684    nativeMethodStrategy,
4685    accessControlContext,
4686    initializationStrategy,
4687    redefinitionStrategy,
4688    bootstrapInjectionStrategy,
4689    lambdaInstrumentationStrategy,
4690    descriptionStrategy,
4691    installationStrategy,
4692    ignoredTypeMatcher,
4693    transformation);
4694    }
4695   
 
4696  148 toggle @Override
4697    public AgentBuilder with(TypeLocator typeLocator) {
4698  148 return new Default(byteBuddy,
4699    typeLocator,
4700    typeStrategy,
4701    listener,
4702    nativeMethodStrategy,
4703    accessControlContext,
4704    initializationStrategy,
4705    redefinitionStrategy,
4706    bootstrapInjectionStrategy,
4707    lambdaInstrumentationStrategy,
4708    descriptionStrategy,
4709    installationStrategy,
4710    ignoredTypeMatcher,
4711    transformation);
4712    }
4713   
 
4714  5 toggle @Override
4715    public AgentBuilder enableNativeMethodPrefix(String prefix) {
4716  5 return new Default(byteBuddy,
4717    typeLocator,
4718    typeStrategy,
4719    listener,
4720    NativeMethodStrategy.ForPrefix.of(prefix),
4721    accessControlContext,
4722    initializationStrategy,
4723    redefinitionStrategy,
4724    bootstrapInjectionStrategy,
4725    lambdaInstrumentationStrategy,
4726    descriptionStrategy,
4727    installationStrategy,
4728    ignoredTypeMatcher,
4729    transformation);
4730    }
4731   
 
4732  32 toggle @Override
4733    public AgentBuilder disableNativeMethodPrefix() {
4734  32 return new Default(byteBuddy,
4735    typeLocator,
4736    typeStrategy,
4737    listener,
4738    NativeMethodStrategy.Disabled.INSTANCE,
4739    accessControlContext,
4740    initializationStrategy,
4741    redefinitionStrategy,
4742    bootstrapInjectionStrategy,
4743    lambdaInstrumentationStrategy,
4744    descriptionStrategy,
4745    installationStrategy,
4746    ignoredTypeMatcher,
4747    transformation);
4748    }
4749   
 
4750  32 toggle @Override
4751    public AgentBuilder with(AccessControlContext accessControlContext) {
4752  32 return new Default(byteBuddy,
4753    typeLocator,
4754    typeStrategy,
4755    listener,
4756    nativeMethodStrategy,
4757    accessControlContext,
4758    initializationStrategy,
4759    redefinitionStrategy,
4760    bootstrapInjectionStrategy,
4761    lambdaInstrumentationStrategy,
4762    descriptionStrategy,
4763    installationStrategy,
4764    ignoredTypeMatcher,
4765    transformation);
4766    }
4767   
 
4768  64 toggle @Override
4769    public AgentBuilder with(RedefinitionStrategy redefinitionStrategy) {
4770  64 return new Default(byteBuddy,
4771    typeLocator,
4772    typeStrategy,
4773    listener,
4774    nativeMethodStrategy,
4775    accessControlContext,
4776    initializationStrategy,
4777    redefinitionStrategy,
4778    bootstrapInjectionStrategy,
4779    lambdaInstrumentationStrategy,
4780    descriptionStrategy,
4781    installationStrategy,
4782    ignoredTypeMatcher,
4783    transformation);
4784    }
4785   
 
4786  81 toggle @Override
4787    public AgentBuilder with(InitializationStrategy initializationStrategy) {
4788  81 return new Default(byteBuddy,
4789    typeLocator,
4790    typeStrategy,
4791    listener,
4792    nativeMethodStrategy,
4793    accessControlContext,
4794    initializationStrategy,
4795    redefinitionStrategy,
4796    bootstrapInjectionStrategy,
4797    lambdaInstrumentationStrategy,
4798    descriptionStrategy,
4799    installationStrategy,
4800    ignoredTypeMatcher,
4801    transformation);
4802    }
4803   
 
4804  36 toggle @Override
4805    public AgentBuilder with(LambdaInstrumentationStrategy lambdaInstrumentationStrategy) {
4806  36 return new Default(byteBuddy,
4807    typeLocator,
4808    typeStrategy,
4809    listener,
4810    nativeMethodStrategy,
4811    accessControlContext,
4812    initializationStrategy,
4813    redefinitionStrategy,
4814    bootstrapInjectionStrategy,
4815    lambdaInstrumentationStrategy,
4816    descriptionStrategy,
4817    installationStrategy,
4818    ignoredTypeMatcher,
4819    transformation);
4820    }
4821   
 
4822  8 toggle @Override
4823    public AgentBuilder with(DescriptionStrategy descriptionStrategy) {
4824  8 return new Default(byteBuddy,
4825    typeLocator,
4826    typeStrategy,
4827    listener,
4828    nativeMethodStrategy,
4829    accessControlContext,
4830    initializationStrategy,
4831    redefinitionStrategy,
4832    bootstrapInjectionStrategy,
4833    lambdaInstrumentationStrategy,
4834    descriptionStrategy,
4835    installationStrategy,
4836    ignoredTypeMatcher,
4837    transformation);
4838    }
4839   
 
4840  32 toggle @Override
4841    public AgentBuilder with(InstallationStrategy installationStrategy) {
4842  32 return new Default(byteBuddy,
4843    typeLocator,
4844    typeStrategy,
4845    listener,
4846    nativeMethodStrategy,
4847    accessControlContext,
4848    initializationStrategy,
4849    redefinitionStrategy,
4850    bootstrapInjectionStrategy,
4851    lambdaInstrumentationStrategy,
4852    descriptionStrategy,
4853    installationStrategy,
4854    ignoredTypeMatcher,
4855    transformation);
4856    }
4857   
 
4858  0 toggle @Override
4859    public AgentBuilder enableBootstrapInjection(Instrumentation instrumentation, File folder) {
4860  0 return new Default(byteBuddy,
4861    typeLocator,
4862    typeStrategy,
4863    listener,
4864    nativeMethodStrategy,
4865    accessControlContext,
4866    initializationStrategy,
4867    redefinitionStrategy,
4868    new BootstrapInjectionStrategy.Enabled(folder, instrumentation),
4869    lambdaInstrumentationStrategy,
4870    descriptionStrategy,
4871    installationStrategy,
4872    ignoredTypeMatcher,
4873    transformation);
4874    }
4875   
 
4876  0 toggle @Override
4877    public AgentBuilder disableBootstrapInjection() {
4878  0 return new Default(byteBuddy,
4879    typeLocator,
4880    typeStrategy,
4881    listener,
4882    nativeMethodStrategy,
4883    accessControlContext,
4884    initializationStrategy,
4885    redefinitionStrategy,
4886    BootstrapInjectionStrategy.Disabled.INSTANCE,
4887    lambdaInstrumentationStrategy,
4888    descriptionStrategy,
4889    installationStrategy,
4890    ignoredTypeMatcher,
4891    transformation);
4892    }
4893   
 
4894  1 toggle @Override
4895    public AgentBuilder disableClassFormatChanges() {
4896  1 return new Default(byteBuddy.with(Implementation.Context.Disabled.Factory.INSTANCE),
4897    typeLocator,
4898    TypeStrategy.Default.REDEFINE_DECLARED_ONLY,
4899    listener,
4900    nativeMethodStrategy,
4901    accessControlContext,
4902    InitializationStrategy.NoOp.INSTANCE,
4903    redefinitionStrategy,
4904    bootstrapInjectionStrategy,
4905    lambdaInstrumentationStrategy,
4906    descriptionStrategy,
4907    installationStrategy,
4908    ignoredTypeMatcher,
4909    transformation);
4910    }
4911   
 
4912  0 toggle @Override
4913    public AgentBuilder assureReadEdgeTo(Instrumentation instrumentation, Class<?>... type) {
4914  0 return JavaModule.isSupported()
4915    ? with(Listener.ModuleReadEdgeCompleting.of(instrumentation, false, type))
4916    : this;
4917    }
4918   
 
4919  0 toggle @Override
4920    public AgentBuilder assureReadEdgeTo(Instrumentation instrumentation, JavaModule... module) {
4921  0 return assureReadEdgeTo(instrumentation, Arrays.asList(module));
4922    }
4923   
 
4924  0 toggle @Override
4925    public AgentBuilder assureReadEdgeTo(Instrumentation instrumentation, Collection<? extends JavaModule> modules) {
4926  0 return with(new Listener.ModuleReadEdgeCompleting(instrumentation, false, new HashSet<JavaModule>(modules)));
4927    }
4928   
 
4929  0 toggle @Override
4930    public AgentBuilder assureReadEdgeFromAndTo(Instrumentation instrumentation, Class<?>... type) {
4931  0 return JavaModule.isSupported()
4932    ? with(Listener.ModuleReadEdgeCompleting.of(instrumentation, true, type))
4933    : this;
4934    }
4935   
 
4936  0 toggle @Override
4937    public AgentBuilder assureReadEdgeFromAndTo(Instrumentation instrumentation, JavaModule... module) {
4938  0 return assureReadEdgeFromAndTo(instrumentation, Arrays.asList(module));
4939    }
4940   
 
4941  0 toggle @Override
4942    public AgentBuilder assureReadEdgeFromAndTo(Instrumentation instrumentation, Collection<? extends JavaModule> modules) {
4943  0 return with(new Listener.ModuleReadEdgeCompleting(instrumentation, true, new HashSet<JavaModule>(modules)));
4944    }
4945   
 
4946  138 toggle @Override
4947    public Identified.Narrowable type(RawMatcher matcher) {
4948  138 return new Transforming(matcher, Transformer.NoOp.INSTANCE, false);
4949    }
4950   
 
4951  31 toggle @Override
4952    public Identified.Narrowable type(ElementMatcher<? super TypeDescription> typeMatcher) {
4953  31 return type(typeMatcher, any());
4954    }
4955   
 
4956  107 toggle @Override
4957    public Identified.Narrowable type(ElementMatcher<? super TypeDescription> typeMatcher, ElementMatcher<? super ClassLoader> classLoaderMatcher) {
4958  107 return type(typeMatcher, classLoaderMatcher, any());
4959    }
4960   
 
4961  107 toggle @Override
4962    public Identified.Narrowable type(ElementMatcher<? super TypeDescription> typeMatcher,
4963    ElementMatcher<? super ClassLoader> classLoaderMatcher,
4964    ElementMatcher<? super JavaModule> moduleMatcher) {
4965  107 return type(new RawMatcher.ForElementMatchers(typeMatcher, classLoaderMatcher, not(supportsModules()).or(moduleMatcher)));
4966    }
4967   
 
4968  142 toggle @Override
4969    public Ignored ignore(ElementMatcher<? super TypeDescription> typeMatcher) {
4970  142 return ignore(typeMatcher, any());
4971    }
4972   
 
4973  143 toggle @Override
4974    public Ignored ignore(ElementMatcher<? super TypeDescription> typeMatcher, ElementMatcher<? super ClassLoader> classLoaderMatcher) {
4975  143 return ignore(typeMatcher, classLoaderMatcher, any());
4976    }
4977   
 
4978  143 toggle @Override
4979    public Ignored ignore(ElementMatcher<? super TypeDescription> typeMatcher,
4980    ElementMatcher<? super ClassLoader> classLoaderMatcher,
4981    ElementMatcher<? super JavaModule> moduleMatcher) {
4982  143 return ignore(new RawMatcher.ForElementMatchers(typeMatcher, classLoaderMatcher, not(supportsModules()).or(moduleMatcher)));
4983    }
4984   
 
4985  143 toggle @Override
4986    public Ignored ignore(RawMatcher rawMatcher) {
4987  143 return new Ignoring(rawMatcher);
4988    }
4989   
 
4990  153 toggle @Override
4991    public ClassFileTransformer makeRaw() {
4992  153 return ExecutingTransformer.FACTORY.make(byteBuddy,
4993    typeLocator,
4994    typeStrategy,
4995    listener,
4996    nativeMethodStrategy,
4997    accessControlContext,
4998    initializationStrategy,
4999    bootstrapInjectionStrategy,
5000    descriptionStrategy,
5001    ignoredTypeMatcher,
5002    transformation);
5003    }
5004   
 
5005  153 toggle @Override
5006    public ClassFileTransformer installOn(Instrumentation instrumentation) {
5007  153 ClassFileTransformer classFileTransformer = makeRaw();
5008  153 instrumentation.addTransformer(classFileTransformer, redefinitionStrategy.isRetransforming(instrumentation));
5009  151 try {
5010  151 if (nativeMethodStrategy.isEnabled(instrumentation)) {
5011  4 instrumentation.setNativeMethodPrefix(classFileTransformer, nativeMethodStrategy.getPrefix());
5012    }
5013  151 lambdaInstrumentationStrategy.apply(byteBuddy, instrumentation, classFileTransformer);
5014  151 if (redefinitionStrategy.isEnabled()) {
5015  62 RedefinitionStrategy.Collector collector = redefinitionStrategy.makeCollector(transformation);
5016  62 for (Class<?> type : instrumentation.getAllLoadedClasses()) {
5017  239117 TypeDescription typeDescription = descriptionStrategy.apply(type, typeLocator);
5018  239117 JavaModule module = JavaModule.ofType(type);
5019  239117 try {
5020  239113 if (!instrumentation.isModifiableClass(type) || !collector.consider(typeDescription, type, ignoredTypeMatcher)) {
5021  239079 try {
5022  239079 try {
5023  239079 listener.onIgnored(typeDescription, type.getClassLoader(), module);
5024    } finally {
5025  239079 listener.onComplete(typeDescription.getName(), type.getClassLoader(), module);
5026    }
5027    } catch (Throwable ignored) {
5028    // Ignore exceptions that are thrown by listeners to mimic the behavior of a transformation.
5029    }
5030    }
5031    } catch (Throwable throwable) {
5032  4 try {
5033  4 try {
5034  4 listener.onError(typeDescription.getName(), type.getClassLoader(), module, throwable);
5035    } finally {
5036  4 listener.onComplete(typeDescription.getName(), type.getClassLoader(), module);
5037    }
5038    } catch (Throwable ignored) {
5039    // Ignore exceptions that are thrown by listeners to mimic the behavior of a transformation.
5040    }
5041    }
5042    }
5043  62 collector.apply(instrumentation, typeLocator, listener);
5044    }
5045  149 return classFileTransformer;
5046    } catch (Throwable throwable) {
5047  2 return installationStrategy.onError(instrumentation, classFileTransformer, throwable);
5048    }
5049    }
5050   
 
5051  84 toggle @Override
5052    public ClassFileTransformer installOnByteBuddyAgent() {
5053  84 try {
5054  84 Instrumentation instrumentation = (Instrumentation) ClassLoader.getSystemClassLoader()
5055    .loadClass(INSTALLER_TYPE)
5056    .getDeclaredField(INSTRUMENTATION_FIELD)
5057    .get(STATIC_FIELD);
5058  84 if (instrumentation == null) {
5059  0 throw new IllegalStateException("The Byte Buddy agent is not installed");
5060    }
5061  84 return installOn(instrumentation);
5062    } catch (RuntimeException exception) {
5063  0 throw exception;
5064    } catch (Exception exception) {
5065  0 throw new IllegalStateException("The Byte Buddy agent is not installed or not accessible", exception);
5066    }
5067    }
5068   
 
5069  28 toggle @Override
5070    public boolean equals(Object other) {
5071  3 if (this == other) return true;
5072  6 if (other == null || getClass() != other.getClass()) return false;
5073  19 Default aDefault = (Default) other;
5074  19 return typeLocator.equals(aDefault.typeLocator)
5075    && byteBuddy.equals(aDefault.byteBuddy)
5076    && listener.equals(aDefault.listener)
5077    && nativeMethodStrategy.equals(aDefault.nativeMethodStrategy)
5078    && typeStrategy.equals(aDefault.typeStrategy)
5079    && accessControlContext.equals(aDefault.accessControlContext)
5080    && initializationStrategy == aDefault.initializationStrategy
5081    && redefinitionStrategy == aDefault.redefinitionStrategy
5082    && bootstrapInjectionStrategy.equals(aDefault.bootstrapInjectionStrategy)
5083    && lambdaInstrumentationStrategy.equals(aDefault.lambdaInstrumentationStrategy)
5084    && descriptionStrategy.equals(aDefault.descriptionStrategy)
5085    && installationStrategy.equals(aDefault.installationStrategy)
5086    && ignoredTypeMatcher.equals(aDefault.ignoredTypeMatcher)
5087    && transformation.equals(aDefault.transformation);
5088    }
5089   
 
5090  21 toggle @Override
5091    public int hashCode() {
5092  21 int result = byteBuddy.hashCode();
5093  21 result = 31 * result + typeLocator.hashCode();
5094  21 result = 31 * result + listener.hashCode();
5095  21 result = 31 * result + typeStrategy.hashCode();
5096  21 result = 31 * result + nativeMethodStrategy.hashCode();
5097  21 result = 31 * result + accessControlContext.hashCode();
5098  21 result = 31 * result + initializationStrategy.hashCode();
5099  21 result = 31 * result + redefinitionStrategy.hashCode();
5100  21 result = 31 * result + bootstrapInjectionStrategy.hashCode();
5101  21 result = 31 * result + lambdaInstrumentationStrategy.hashCode();
5102  21 result = 31 * result + descriptionStrategy.hashCode();
5103  21 result = 31 * result + installationStrategy.hashCode();
5104  21 result = 31 * result + ignoredTypeMatcher.hashCode();
5105  21 result = 31 * result + transformation.hashCode();
5106  21 return result;
5107    }
5108   
 
5109  48 toggle @Override
5110    public String toString() {
5111  48 return "AgentBuilder.Default{" +
5112    "byteBuddy=" + byteBuddy +
5113    ", typeLocator=" + typeLocator +
5114    ", typeStrategy=" + typeStrategy +
5115    ", listener=" + listener +
5116    ", nativeMethodStrategy=" + nativeMethodStrategy +
5117    ", accessControlContext=" + accessControlContext +
5118    ", initializationStrategy=" + initializationStrategy +
5119    ", redefinitionStrategy=" + redefinitionStrategy +
5120    ", bootstrapInjectionStrategy=" + bootstrapInjectionStrategy +
5121    ", lambdaInstrumentationStrategy=" + lambdaInstrumentationStrategy +
5122    ", descriptionStrategy=" + descriptionStrategy +
5123    ", installationStrategy=" + installationStrategy +
5124    ", ignoredTypeMatcher=" + ignoredTypeMatcher +
5125    ", transformation=" + transformation +
5126    '}';
5127    }
5128   
5129    /**
5130    * An injection strategy for injecting classes into the bootstrap class loader.
5131    */
 
5132    protected interface BootstrapInjectionStrategy {
5133   
5134    /**
5135    * Creates an injector for the bootstrap class loader.
5136    *
5137    * @param protectionDomain The protection domain to be used.
5138    * @return A class injector for the bootstrap class loader.
5139    */
5140    ClassInjector make(ProtectionDomain protectionDomain);
5141   
5142    /**
5143    * A disabled bootstrap injection strategy.
5144    */
 
5145    enum Disabled implements BootstrapInjectionStrategy {
5146   
5147    /**
5148    * The singleton instance.
5149    */
5150    INSTANCE;
5151   
 
5152  1 toggle @Override
5153    public ClassInjector make(ProtectionDomain protectionDomain) {
5154  1 throw new IllegalStateException("Injecting classes into the bootstrap class loader was not enabled");
5155    }
5156   
 
5157  33 toggle @Override
5158    public String toString() {
5159  33 return "AgentBuilder.Default.BootstrapInjectionStrategy.Disabled." + name();
5160    }
5161    }
5162   
5163    /**
5164    * An enabled bootstrap injection strategy.
5165    */
 
5166    class Enabled implements BootstrapInjectionStrategy {
5167   
5168    /**
5169    * The folder in which jar files are to be saved.
5170    */
5171    private final File folder;
5172   
5173    /**
5174    * The instrumentation to use for appending jar files.
5175    */
5176    private final Instrumentation instrumentation;
5177   
5178    /**
5179    * Creates a new enabled bootstrap class loader injection strategy.
5180    *
5181    * @param folder The folder in which jar files are to be saved.
5182    * @param instrumentation The instrumentation to use for appending jar files.
5183    */
 
5184  5 toggle public Enabled(File folder, Instrumentation instrumentation) {
5185  5 this.folder = folder;
5186  5 this.instrumentation = instrumentation;
5187    }
5188   
 
5189  1 toggle @Override
5190    public ClassInjector make(ProtectionDomain protectionDomain) {
5191  1 return ClassInjector.UsingInstrumentation.of(folder, ClassInjector.UsingInstrumentation.Target.BOOTSTRAP, instrumentation);
5192    }
5193   
 
5194  6 toggle @Override
5195    public boolean equals(Object other) {
5196  1 if (this == other) return true;
5197  2 if (other == null || getClass() != other.getClass()) return false;
5198  3 Enabled enabled = (Enabled) other;
5199  3 return folder.equals(enabled.folder) && instrumentation.equals(enabled.instrumentation);
5200    }
5201   
 
5202  4 toggle @Override
5203    public int hashCode() {
5204  4 int result = folder.hashCode();
5205  4 result = 31 * result + instrumentation.hashCode();
5206  4 return result;
5207    }
5208   
 
5209  4 toggle @Override
5210    public String toString() {
5211  4 return "AgentBuilder.Default.BootstrapInjectionStrategy.Enabled{" +
5212    "folder=" + folder +
5213    ", instrumentation=" + instrumentation +
5214    '}';
5215    }
5216    }
5217    }
5218   
5219    /**
5220    * A strategy for determining if a native method name prefix should be used when rebasing methods.
5221    */
 
5222    protected interface NativeMethodStrategy {
5223   
5224    /**
5225    * Determines if this strategy enables name prefixing for native methods.
5226    *
5227    * @param instrumentation The instrumentation used.
5228    * @return {@code true} if this strategy indicates that a native method prefix should be used.
5229    */
5230    boolean isEnabled(Instrumentation instrumentation);
5231   
5232    /**
5233    * Resolves the method name transformer for this strategy.
5234    *
5235    * @return A method name transformer for this strategy.
5236    */
5237    MethodNameTransformer resolve();
5238   
5239    /**
5240    * Returns the method prefix if the strategy is enabled. This method must only be called if this strategy enables prefixing.
5241    *
5242    * @return The method prefix.
5243    */
5244    String getPrefix();
5245   
5246    /**
5247    * A native method strategy that suffixes method names with a random suffix and disables native method rebasement.
5248    */
 
5249    enum Disabled implements NativeMethodStrategy {
5250   
5251    /**
5252    * The singleton instance.
5253    */
5254    INSTANCE;
5255   
 
5256  100 toggle @Override
5257    public MethodNameTransformer resolve() {
5258  100 return MethodNameTransformer.Suffixing.withRandomSuffix();
5259    }
5260   
 
5261  148 toggle @Override
5262    public boolean isEnabled(Instrumentation instrumentation) {
5263  148 return false;
5264    }
5265   
 
5266  1 toggle @Override
5267    public String getPrefix() {
5268  1 throw new IllegalStateException("A disabled native method strategy does not define a method name prefix");
5269    }
5270   
 
5271  33 toggle @Override
5272    public String toString() {
5273  33 return "AgentBuilder.Default.NativeMethodStrategy.Disabled." + name();
5274    }
5275    }
5276   
5277    /**
5278    * A native method strategy that prefixes method names with a fixed value for supporting rebasing of native methods.
5279    */
 
5280    class ForPrefix implements NativeMethodStrategy {
5281   
5282    /**
5283    * The method name prefix.
5284    */
5285    private final String prefix;
5286   
5287    /**
5288    * Creates a new name prefixing native method strategy.
5289    *
5290    * @param prefix The method name prefix.
5291    */
 
5292  11 toggle protected ForPrefix(String prefix) {
5293  11 this.prefix = prefix;
5294    }
5295   
5296    /**
5297    * Creates a new native method strategy for prefixing method names.
5298    *
5299    * @param prefix The method name prefix.
5300    * @return An appropriate native method strategy.
5301    */
 
5302  6 toggle protected static NativeMethodStrategy of(String prefix) {
5303  6 if (prefix.length() == 0) {
5304  2 throw new IllegalArgumentException("A method name prefix must not be the empty string");
5305    }
5306  4 return new ForPrefix(prefix);
5307    }
5308   
 
5309  5 toggle @Override
5310    public MethodNameTransformer resolve() {
5311  5 return new MethodNameTransformer.Prefixing(prefix);
5312    }
5313   
 
5314  6 toggle @Override
5315    public boolean isEnabled(Instrumentation instrumentation) {
5316  6 if (!instrumentation.isNativeMethodPrefixSupported()) {
5317  1 throw new IllegalArgumentException("A prefix for native methods is not supported: " + instrumentation);
5318    }
5319  5 return true;
5320    }
5321   
 
5322  5 toggle @Override
5323    public String getPrefix() {
5324  5 return prefix;
5325    }
5326   
 
5327  5 toggle @Override
5328    public boolean equals(Object other) {
5329  5 return this == other || !(other == null || getClass() != other.getClass()) && prefix.equals(((ForPrefix) other).prefix);
5330    }
5331   
 
5332  3 toggle @Override
5333    public int hashCode() {
5334  3 return prefix.hashCode();
5335    }
5336   
 
5337  3 toggle @Override
5338    public String toString() {
5339  3 return "AgentBuilder.Default.NativeMethodStrategy.ForPrefix{" +
5340    "prefix='" + prefix + '\'' +
5341    '}';
5342    }
5343    }
5344    }
5345   
5346    /**
5347    * A transformation serves as a handler for modifying a class.
5348    */
 
5349    protected interface Transformation {
5350   
5351    /**
5352    * Resolves an attempted transformation to a specific transformation.
5353    *
5354    * @param typeDescription A description of the type that is to be transformed.
5355    * @param classLoader The class loader of the type being transformed.
5356    * @param module The transformed type's module or {@code null} if the current VM does not support modules.
5357    * @param classBeingRedefined In case of a type redefinition, the loaded type being transformed or {@code null} if that is not the case.
5358    * @param protectionDomain The protection domain of the type being transformed.
5359    * @param ignoredTypeMatcher Identifies types that should not be instrumented.
5360    * @return A resolution for the given type.
5361    */
5362    Resolution resolve(TypeDescription typeDescription,
5363    ClassLoader classLoader,
5364    JavaModule module,
5365    Class<?> classBeingRedefined,
5366    ProtectionDomain protectionDomain,
5367    RawMatcher ignoredTypeMatcher);
5368   
5369    /**
5370    * A resolution to a transformation.
5371    */
 
5372    interface Resolution {
5373   
5374    /**
5375    * Returns the sort of this resolution.
5376    *
5377    * @return The sort of this resolution.
5378    */
5379    Sort getSort();
5380   
5381    /**
5382    * Resolves this resolution as a decorator of the supplied resolution.
5383    *
5384    * @param resolution The resolution for which this resolution should serve as a decorator.
5385    * @return A resolution where this resolution is applied as a decorator if this resolution is alive.
5386    */
5387    Resolution asDecoratorOf(Resolution resolution);
5388   
5389    /**
5390    * Resolves this resolution as a decorator of the supplied resolution.
5391    *
5392    * @param resolution The resolution for which this resolution should serve as a decorator.
5393    * @return A resolution where this resolution is applied as a decorator if this resolution is alive.
5394    */
5395    Resolution prepend(Decoratable resolution);
5396   
5397    /**
5398    * Transforms a type or returns {@code null} if a type is not to be transformed.
5399    *
5400    * @param initializationStrategy The initialization strategy to use.
5401    * @param classFileLocator The class file locator to use.
5402    * @param typeStrategy The definition handler to use.
5403    * @param byteBuddy The Byte Buddy instance to use.
5404    * @param methodNameTransformer The method name transformer to be used.
5405    * @param bootstrapInjectionStrategy The bootstrap injection strategy to be used.
5406    * @param accessControlContext The access control context to be used.
5407    * @param listener The listener to be invoked to inform about an applied or non-applied transformation.
5408    * @return The class file of the transformed class or {@code null} if no transformation is attempted.
5409    */
5410    byte[] apply(InitializationStrategy initializationStrategy,
5411    ClassFileLocator classFileLocator,
5412    TypeStrategy typeStrategy,
5413    ByteBuddy byteBuddy,
5414    NativeMethodStrategy methodNameTransformer,
5415    BootstrapInjectionStrategy bootstrapInjectionStrategy,
5416    AccessControlContext accessControlContext,
5417    Listener listener);
5418   
5419    /**
5420    * Describes a specific sort of a {@link Resolution}.
5421    */
 
5422    enum Sort {
5423   
5424    /**
5425    * A terminal resolution. After discovering such a resolution, no further transformers are considered.
5426    */
5427    TERMINAL(true),
5428   
5429    /**
5430    * A resolution that can serve as a decorator for another resolution. After discovering such a resolution
5431    * further transformations are considered where the represented resolution is prepended if applicable.
5432    */
5433    DECORATOR(true),
5434   
5435    /**
5436    * A non-resolved resolution.
5437    */
5438    UNDEFINED(false);
5439   
5440    /**
5441    * Indicates if this sort represents an active resolution.
5442    */
5443    private final boolean alive;
5444   
5445    /**
5446    * Creates a new resolution sort.
5447    *
5448    * @param alive Indicates if this sort represents an active resolution.
5449    */
 
5450  3 toggle Sort(boolean alive) {
5451  3 this.alive = alive;
5452    }
5453   
5454    /**
5455    * Returns {@code true} if this resolution is alive.
5456    *
5457    * @return {@code true} if this resolution is alive.
5458    */
 
5459  217091 toggle protected boolean isAlive() {
5460  217091 return alive;
5461    }
5462   
 
5463  3 toggle @Override
5464    public String toString() {
5465  3 return "AgentBuilder.Default.Transformation.Resolution.Sort." + name();
5466    }
5467    }
5468   
5469    /**
5470    * A resolution that can be decorated by a transformer.
5471    */
 
5472    interface Decoratable extends Resolution {
5473   
5474    /**
5475    * Appends the supplied transformer to this resolution.
5476    *
5477    * @param transformer The transformer to append to the transformer that is represented bz this instance.
5478    * @return A new resolution with the supplied transformer appended to this transformer.
5479    */
5480    Resolution append(Transformer transformer);
5481    }
5482   
5483    /**
5484    * A canonical implementation of a non-resolved resolution.
5485    */
 
5486    class Unresolved implements Resolution {
5487   
5488    /**
5489    * The type that is not transformed.
5490    */
5491    private final TypeDescription typeDescription;
5492   
5493    /**
5494    * The unresolved type's class loader.
5495    */
5496    private final ClassLoader classLoader;
5497   
5498    /**
5499    * The non-transformed type's module or {@code null} if the current VM does not support modules.
5500    */
5501    private final JavaModule module;
5502   
5503    /**
5504    * Creates a new unresolved resolution.
5505    *
5506    * @param typeDescription The type that is not transformed.
5507    * @param classLoader The unresolved type's class loader.
5508    * @param module The non-transformed type's module or {@code null} if the current VM does not support modules.
5509    */
 
5510  478275 toggle protected Unresolved(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
5511  478275 this.typeDescription = typeDescription;
5512  478275 this.classLoader = classLoader;
5513  478275 this.module = module;
5514    }
5515   
 
5516  477943 toggle @Override
5517    public Sort getSort() {
5518  477943 return Sort.UNDEFINED;
5519    }
5520   
 
5521  145 toggle @Override
5522    public Resolution asDecoratorOf(Resolution resolution) {
5523  145 return resolution;
5524    }
5525   
 
5526  0 toggle @Override
5527    public Resolution prepend(Decoratable resolution) {
5528  0 return resolution;
5529    }
5530   
 
5531  178 toggle @Override
5532    public byte[] apply(InitializationStrategy initializationStrategy,
5533    ClassFileLocator classFileLocator,
5534    TypeStrategy typeStrategy,
5535    ByteBuddy byteBuddy,
5536    NativeMethodStrategy methodNameTransformer,
5537    BootstrapInjectionStrategy bootstrapInjectionStrategy,
5538    AccessControlContext accessControlContext,
5539    Listener listener) {
5540  178 listener.onIgnored(typeDescription, classLoader, module);
5541  178 return NO_TRANSFORMATION;
5542    }
5543   
 
5544  7 toggle @Override
5545    public boolean equals(Object object) {
5546  1 if (this == object) return true;
5547  2 if (object == null || getClass() != object.getClass()) return false;
5548  4 Unresolved that = (Unresolved) object;
5549  4 return typeDescription.equals(that.typeDescription)
5550  3 && (classLoader != null ? classLoader.equals(that.classLoader) : that.classLoader == null)
5551  2 && (module != null ? module.equals(that.module) : that.module == null);
5552    }
5553   
 
5554  5 toggle @Override
5555    public int hashCode() {
5556  5 int result = typeDescription.hashCode();
5557  5 result = 31 * result + (classLoader != null ? classLoader.hashCode() : 0);
5558  5 result = 31 * result + (module != null ? module.hashCode() : 0);
5559  5 return result;
5560    }
5561   
 
5562  5 toggle @Override
5563    public String toString() {
5564  5 return "AgentBuilder.Default.Transformation.Resolution.Unresolved{" +
5565    "typeDescription=" + typeDescription +
5566    ", classLoader=" + classLoader +
5567    ", module=" + module +
5568    '}';
5569    }
5570    }
5571    }
5572   
5573    /**
5574    * A transformation that does not attempt to transform any type.
5575    */
 
5576    enum Ignored implements Transformation {
5577   
5578    /**
5579    * The singleton instance.
5580    */
5581    INSTANCE;
5582   
 
5583  217239 toggle @Override
5584    public Resolution resolve(TypeDescription typeDescription,
5585    ClassLoader classLoader,
5586    JavaModule module,
5587    Class<?> classBeingRedefined,
5588    ProtectionDomain protectionDomain,
5589    RawMatcher ignoredTypeMatcher) {
5590  217239 return new Resolution.Unresolved(typeDescription, classLoader, module);
5591    }
5592   
 
5593  33 toggle @Override
5594    public String toString() {
5595  33 return "AgentBuilder.Default.Transformation.Ignored." + name();
5596    }
5597    }
5598   
5599    /**
5600    * A simple, active transformation.
5601    */
 
5602    class Simple implements Transformation {
5603   
5604    /**
5605    * The raw matcher that is represented by this transformation.
5606    */
5607    private final RawMatcher rawMatcher;
5608   
5609    /**
5610    * The transformer that is represented by this transformation.
5611    */
5612    private final Transformer transformer;
5613   
5614    /**
5615    * {@code true} if this transformer serves as a decorator.
5616    */
5617    private final boolean decorator;
5618   
5619    /**
5620    * Creates a new transformation.
5621    *
5622    * @param rawMatcher The raw matcher that is represented by this transformation.
5623    * @param transformer The transformer that is represented by this transformation.
5624    * @param decorator {@code true} if this transformer serves as a decorator.
5625    */
 
5626  147 toggle protected Simple(RawMatcher rawMatcher, Transformer transformer, boolean decorator) {
5627  147 this.rawMatcher = rawMatcher;
5628  147 this.transformer = transformer;
5629  147 this.decorator = decorator;
5630    }
5631   
 
5632  130590 toggle @Override
5633    public Transformation.Resolution resolve(TypeDescription typeDescription,
5634    ClassLoader classLoader,
5635    JavaModule module,
5636    Class<?> classBeingRedefined,
5637    ProtectionDomain protectionDomain,
5638    RawMatcher ignoredTypeMatcher) {
5639  130586 return !ignoredTypeMatcher.matches(typeDescription, classLoader, module, classBeingRedefined, protectionDomain)
5640    && rawMatcher.matches(typeDescription, classLoader, module, classBeingRedefined, protectionDomain)
5641    ? new Resolution(typeDescription, classLoader, module, protectionDomain, transformer, decorator)
5642    : new Transformation.Resolution.Unresolved(typeDescription, classLoader, module);
5643    }
5644   
 
5645  7 toggle @Override
5646    public boolean equals(Object other) {
5647  7 return this == other || !(other == null || getClass() != other.getClass())
5648    && decorator == ((Simple) other).decorator
5649    && rawMatcher.equals(((Simple) other).rawMatcher)
5650    && transformer.equals(((Simple) other).transformer);
5651    }
5652   
 
5653  61 toggle @Override
5654    public int hashCode() {
5655  61 int result = rawMatcher.hashCode();
5656  61 result = 31 * result + (decorator ? 1 : 0);
5657  61 result = 31 * result + transformer.hashCode();
5658  61 return result;
5659    }
5660   
 
5661  5 toggle @Override
5662    public String toString() {
5663  5 return "AgentBuilder.Default.Transformation.Simple{" +
5664    "rawMatcher=" + rawMatcher +
5665    ", transformer=" + transformer +
5666    ", decorator=" + decorator +
5667    '}';
5668    }
5669   
5670    /**
5671    * A resolution that performs a type transformation.
5672    */
 
5673    protected static class Resolution implements Transformation.Resolution.Decoratable {
5674   
5675    /**
5676    * A description of the transformed type.
5677    */
5678    private final TypeDescription typeDescription;
5679   
5680    /**
5681    * The class loader of the transformed type.
5682    */
5683    private final ClassLoader classLoader;
5684   
5685    /**
5686    * The transformed type's module or {@code null} if the current VM does not support modules.
5687    */
5688    private final JavaModule module;
5689   
5690    /**
5691    * The protection domain of the transformed type.
5692    */
5693    private final ProtectionDomain protectionDomain;
5694   
5695    /**
5696    * The transformer to be applied.
5697    */
5698    private final Transformer transformer;
5699   
5700    /**
5701    * {@code true} if this transformer serves as a decorator.
5702    */
5703    private final boolean decorator;
5704   
5705    /**
5706    * Creates a new active transformation.
5707    *
5708    * @param typeDescription A description of the transformed type.
5709    * @param classLoader The class loader of the transformed type.
5710    * @param module The transformed type's module or {@code null} if the current VM does not support modules.
5711    * @param protectionDomain The protection domain of the transformed type.
5712    * @param transformer The transformer to be applied.
5713    * @param decorator {@code true} if this transformer serves as a decorator.
5714    */
 
5715  162 toggle protected Resolution(TypeDescription typeDescription,
5716    ClassLoader classLoader,
5717    JavaModule module,
5718    ProtectionDomain protectionDomain,
5719    Transformer transformer,
5720    boolean decorator) {
5721  162 this.typeDescription = typeDescription;
5722  162 this.classLoader = classLoader;
5723  162 this.module = module;
5724  162 this.protectionDomain = protectionDomain;
5725  162 this.transformer = transformer;
5726  162 this.decorator = decorator;
5727    }
5728   
 
5729  188 toggle @Override
5730    public Sort getSort() {
5731  188 return decorator
5732    ? Sort.DECORATOR
5733    : Sort.TERMINAL;
5734    }
5735   
 
5736  9 toggle @Override
5737    public Transformation.Resolution asDecoratorOf(Transformation.Resolution resolution) {
5738  9 return resolution.prepend(this);
5739    }
5740   
 
5741  9 toggle @Override
5742    public Transformation.Resolution prepend(Decoratable resolution) {
5743  9 return resolution.append(transformer);
5744    }
5745   
 
5746  9 toggle @Override
5747    public Transformation.Resolution append(Transformer transformer) {
5748  9 return new Resolution(typeDescription,
5749    classLoader,
5750    module,
5751    protectionDomain,
5752    new Transformer.Compound(this.transformer, transformer),
5753    decorator);
5754    }
5755   
 
5756  102 toggle @Override
5757    public byte[] apply(InitializationStrategy initializationStrategy,
5758    ClassFileLocator classFileLocator,
5759    TypeStrategy typeStrategy,
5760    ByteBuddy byteBuddy,
5761    NativeMethodStrategy methodNameTransformer,
5762    BootstrapInjectionStrategy bootstrapInjectionStrategy,
5763    AccessControlContext accessControlContext,
5764    Listener listener) {
5765  102 InitializationStrategy.Dispatcher dispatcher = initializationStrategy.dispatcher();
5766  102 DynamicType.Unloaded<?> dynamicType = dispatcher.apply(transformer.transform(typeStrategy.builder(typeDescription,
5767    byteBuddy,
5768    classFileLocator,
5769    methodNameTransformer.resolve()), typeDescription, classLoader)).make();
5770  102 dispatcher.register(dynamicType, classLoader, new BootstrapClassLoaderCapableInjectorFactory(bootstrapInjectionStrategy,
5771    classLoader,
5772    protectionDomain,
5773    accessControlContext));
5774  102 listener.onTransformation(typeDescription, classLoader, module, dynamicType);
5775  102 return dynamicType.getBytes();
5776    }
5777   
 
5778  10 toggle @Override
5779    public boolean equals(Object other) {
5780  1 if (this == other) return true;
5781  2 if (other == null || getClass() != other.getClass()) return false;
5782  7 Resolution that = (Resolution) other;
5783  7 return typeDescription.equals(that.typeDescription)
5784    && decorator == that.decorator
5785  5 && !(classLoader != null ? !classLoader.equals(that.classLoader) : that.classLoader != null)
5786  4 && !(module != null ? !module.equals(that.module) : that.module != null)
5787  3 && !(protectionDomain != null ? !protectionDomain.equals(that.protectionDomain) : that.protectionDomain != null)
5788    && transformer.equals(that.transformer);
5789    }
5790   
 
5791  8 toggle @Override
5792    public int hashCode() {
5793  8 int result = typeDescription.hashCode();
5794  8 result = 31 * result + (decorator ? 1 : 0);
5795  8 result = 31 * result + (classLoader != null ? classLoader.hashCode() : 0);
5796  8 result = 31 * result + (module != null ? module.hashCode() : 0);
5797  8 result = 31 * result + (protectionDomain != null ? protectionDomain.hashCode() : 0);
5798  8 result = 31 * result + transformer.hashCode();
5799  8 return result;
5800    }
5801   
 
5802  8 toggle @Override
5803    public String toString() {
5804  8 return "AgentBuilder.Default.Transformation.Simple.Resolution{" +
5805    "typeDescription=" + typeDescription +
5806    ", classLoader=" + classLoader +
5807    ", module=" + module +
5808    ", protectionDomain=" + protectionDomain +
5809    ", transformer=" + transformer +
5810    ", decorator=" + decorator +
5811    '}';
5812    }
5813   
5814    /**
5815    * An injector factory that resolves to a bootstrap class loader injection if this is necessary and enabled.
5816    */
 
5817    protected static class BootstrapClassLoaderCapableInjectorFactory implements InitializationStrategy.Dispatcher.InjectorFactory {
5818   
5819    /**
5820    * The bootstrap injection strategy being used.
5821    */
5822    private final BootstrapInjectionStrategy bootstrapInjectionStrategy;
5823   
5824    /**
5825    * The class loader for which to create an injection factory.
5826    */
5827    private final ClassLoader classLoader;
5828   
5829    /**
5830    * The protection domain of the created classes.
5831    */
5832    private final ProtectionDomain protectionDomain;
5833   
5834    /**
5835    * The access control context to be used.
5836    */
5837    private final AccessControlContext accessControlContext;
5838   
5839    /**
5840    * Creates a new bootstrap class loader capable injector factory.
5841    *
5842    * @param bootstrapInjectionStrategy The bootstrap injection strategy being used.
5843    * @param classLoader The class loader for which to create an injection factory.
5844    * @param protectionDomain The protection domain of the created classes.
5845    * @param accessControlContext The access control context to be used.
5846    */
 
5847  116 toggle protected BootstrapClassLoaderCapableInjectorFactory(BootstrapInjectionStrategy bootstrapInjectionStrategy,
5848    ClassLoader classLoader,
5849    ProtectionDomain protectionDomain,
5850    AccessControlContext accessControlContext) {
5851  116 this.bootstrapInjectionStrategy = bootstrapInjectionStrategy;
5852  116 this.classLoader = classLoader;
5853  116 this.protectionDomain = protectionDomain;
5854  116 this.accessControlContext = accessControlContext;
5855    }
5856   
 
5857  22 toggle @Override
5858    public ClassInjector resolve() {
5859  22 return classLoader == null
5860    ? bootstrapInjectionStrategy.make(protectionDomain)
5861    : new ClassInjector.UsingReflection(classLoader, protectionDomain, accessControlContext);
5862    }
5863   
 
5864  20 toggle @Override
5865    public boolean equals(Object other) {
5866  1 if (this == other) return true;
5867  2 if (other == null || getClass() != other.getClass()) return false;
5868  17 BootstrapClassLoaderCapableInjectorFactory that = (BootstrapClassLoaderCapableInjectorFactory) other;
5869  17 return bootstrapInjectionStrategy.equals(that.bootstrapInjectionStrategy)
5870  16 && !(classLoader != null ? !classLoader.equals(that.classLoader) : that.classLoader != null)
5871  15 && !(protectionDomain != null ? !protectionDomain.equals(that.protectionDomain) : that.protectionDomain != null)
5872    && accessControlContext.equals(that.accessControlContext);
5873    }
5874   
 
5875  6 toggle @Override
5876    public int hashCode() {
5877  6 int result = bootstrapInjectionStrategy.hashCode();
5878  6 result = 31 * result + (protectionDomain != null ? protectionDomain.hashCode() : 0);
5879  6 result = 31 * result + (classLoader != null ? classLoader.hashCode() : 0);
5880  6 result = 31 * result + accessControlContext.hashCode();
5881  6 return result;
5882    }
5883   
 
5884  6 toggle @Override
5885    public String toString() {
5886  6 return "AgentBuilder.Default.Transformation.Simple.Resolution.BootstrapClassLoaderCapableInjectorFactory{" +
5887    "bootstrapInjectionStrategy=" + bootstrapInjectionStrategy +
5888    ", classLoader=" + classLoader +
5889    ", protectionDomain=" + protectionDomain +
5890    ", accessControlContext=" + accessControlContext +
5891    '}';
5892    }
5893    }
5894    }
5895    }
5896   
5897    /**
5898    * A compound transformation that applied several transformation in the given order and applies the first active transformation.
5899    */
 
5900    class Compound implements Transformation {
5901   
5902    /**
5903    * The list of transformations to apply in their application order.
5904    */
5905    private final List<? extends Transformation> transformations;
5906   
5907    /**
5908    * Creates a new compound transformation.
5909    *
5910    * @param transformation An array of transformations to apply in their application order.
5911    */
 
5912  145 toggle protected Compound(Transformation... transformation) {
5913  145 this(Arrays.asList(transformation));
5914    }
5915   
5916    /**
5917    * Creates a new compound transformation.
5918    *
5919    * @param transformations A list of transformations to apply in their application order.
5920    */
 
5921  148 toggle protected Compound(List<? extends Transformation> transformations) {
5922  148 this.transformations = transformations;
5923    }
5924   
 
5925  130590 toggle @Override
5926    public Resolution resolve(TypeDescription typeDescription,
5927    ClassLoader classLoader,
5928    JavaModule module,
5929    Class<?> classBeingRedefined,
5930    ProtectionDomain protectionDomain,
5931    RawMatcher ignoredTypeMatcher) {
5932  130590 Resolution current = new Resolution.Unresolved(typeDescription, classLoader, module);
5933  130590 for (Transformation transformation : transformations) {
5934  261044 Resolution resolution = transformation.resolve(typeDescription,
5935    classLoader,
5936    module,
5937    classBeingRedefined,
5938    protectionDomain,
5939    ignoredTypeMatcher);
5940  261040 switch (resolution.getSort()) {
5941  137 case TERMINAL:
5942  137 return current.asDecoratorOf(resolution);
5943  17 case DECORATOR:
5944  17 current = current.asDecoratorOf(resolution);
5945  17 break;
5946  260886 case UNDEFINED:
5947  260886 break;
5948  0 default:
5949  0 throw new IllegalStateException("Unexpected resolution type: " + resolution.getSort());
5950    }
5951    }
5952  130449 return current;
5953    }
5954   
 
5955  10 toggle @Override
5956    public boolean equals(Object other) {
5957  10 return this == other || !(other == null || getClass() != other.getClass())
5958    && transformations.equals(((Compound) other).transformations);
5959    }
5960   
 
5961  62 toggle @Override
5962    public int hashCode() {
5963  62 return transformations.hashCode();
5964    }
5965   
 
5966  6 toggle @Override
5967    public String toString() {
5968  6 return "AgentBuilder.Default.Transformation.Compound{" +
5969    "transformations=" + transformations +
5970    '}';
5971    }
5972    }
5973    }
5974   
5975    /**
5976    * A {@link java.lang.instrument.ClassFileTransformer} that implements the enclosing agent builder's
5977    * configuration.
5978    */
 
5979    protected static class ExecutingTransformer implements ClassFileTransformer {
5980   
5981    /**
5982    * A factory for creating a {@link ClassFileTransformer} that supports the features of the current VM.
5983    */
5984    protected static final Factory FACTORY;
5985   
5986    /*
5987    * Creates a factory for a class file transformer that supports the features of the current VM.
5988    */
 
5989  1 toggle static {
5990  1 Factory factory;
5991  1 try {
5992  1 factory = new Factory.ForJava9CapableVm(new ByteBuddy()
5993    .subclass(ExecutingTransformer.class)
5994    .method(named("transform").and(takesArgument(0, JavaType.MODULE.getTypeStub())))
5995    .intercept(MethodCall.invoke(ExecutingTransformer.class.getDeclaredMethod("transform",
5996    Object.class,
5997    String.class,
5998    Class.class,
5999    ProtectionDomain.class,
6000    byte[].class)).onSuper().withAllArguments())
6001    .make()
6002    .load(ExecutingTransformer.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
6003    .getLoaded()
6004    .getDeclaredConstructor(ByteBuddy.class,
6005    TypeLocator.class,
6006    TypeStrategy.class,
6007    Listener.class,
6008    NativeMethodStrategy.class,
6009    AccessControlContext.class,
6010    InitializationStrategy.class,
6011    BootstrapInjectionStrategy.class,
6012    DescriptionStrategy.class,
6013    RawMatcher.class,
6014    Transformation.class));
6015    } catch (RuntimeException exception) {
6016  0 throw exception;
6017    } catch (Exception ignored) {
6018  0 factory = Factory.ForLegacyVm.INSTANCE;
6019    }
6020  1 FACTORY = factory;
6021    }
6022   
6023    /**
6024    * The Byte Buddy instance to be used.
6025    */
6026    private final ByteBuddy byteBuddy;
6027   
6028    /**
6029    * The type locator to use.
6030    */
6031    private final TypeLocator typeLocator;
6032   
6033    /**
6034    * The definition handler to use.
6035    */
6036    private final TypeStrategy typeStrategy;
6037   
6038    /**
6039    * The listener to notify on transformations.
6040    */
6041    private final Listener listener;
6042   
6043    /**
6044    * The native method strategy to apply.
6045    */
6046    private final NativeMethodStrategy nativeMethodStrategy;
6047   
6048    /**
6049    * The access control context to use for loading classes.
6050    */
6051    private final AccessControlContext accessControlContext;
6052   
6053    /**
6054    * The initialization strategy to use for transformed types.
6055    */
6056    private final InitializationStrategy initializationStrategy;
6057   
6058    /**
6059    * The injection strategy for injecting classes into the bootstrap class loader.
6060    */
6061    private final BootstrapInjectionStrategy bootstrapInjectionStrategy;
6062   
6063    /**
6064    * The description strategy for resolving type descriptions for types.
6065    */
6066    private final DescriptionStrategy descriptionStrategy;
6067   
6068    /**
6069    * Identifies types that should not be instrumented.
6070    */
6071    private final RawMatcher ignoredTypeMatcher;
6072   
6073    /**
6074    * The transformation object for handling type transformations.
6075    */
6076    private final Transformation transformation;
6077   
6078    /**
6079    * Creates a new class file transformer.
6080    *
6081    * @param byteBuddy The Byte Buddy instance to be used.
6082    * @param typeLocator The type locator to use.
6083    * @param typeStrategy The definition handler to use.
6084    * @param listener The listener to notify on transformations.
6085    * @param nativeMethodStrategy The native method strategy to apply.
6086    * @param accessControlContext The access control context to use for loading classes.
6087    * @param initializationStrategy The initialization strategy to use for transformed types.
6088    * @param bootstrapInjectionStrategy The injection strategy for injecting classes into the bootstrap class loader.
6089    * @param descriptionStrategy The description strategy for resolving type descriptions for types.
6090    * @param ignoredTypeMatcher Identifies types that should not be instrumented.
6091    * @param transformation The transformation object for handling type transformations.
6092    */
 
6093  167 toggle public ExecutingTransformer(ByteBuddy byteBuddy,
6094    TypeLocator typeLocator,
6095    TypeStrategy typeStrategy,
6096    Listener listener,
6097    NativeMethodStrategy nativeMethodStrategy,
6098    AccessControlContext accessControlContext,
6099    InitializationStrategy initializationStrategy,
6100    BootstrapInjectionStrategy bootstrapInjectionStrategy,
6101    DescriptionStrategy descriptionStrategy,
6102    RawMatcher ignoredTypeMatcher,
6103    Transformation transformation) {
6104  167 this.byteBuddy = byteBuddy;
6105  167 this.typeLocator = typeLocator;
6106  167 this.typeStrategy = typeStrategy;
6107  167 this.listener = listener;
6108  167 this.nativeMethodStrategy = nativeMethodStrategy;
6109  167 this.accessControlContext = accessControlContext;
6110  167 this.initializationStrategy = initializationStrategy;
6111  167 this.bootstrapInjectionStrategy = bootstrapInjectionStrategy;
6112  167 this.descriptionStrategy = descriptionStrategy;
6113  167 this.ignoredTypeMatcher = ignoredTypeMatcher;
6114  167 this.transformation = transformation;
6115    }
6116   
 
6117  326 toggle @Override
6118    public byte[] transform(ClassLoader classLoader,
6119    String internalTypeName,
6120    Class<?> classBeingRedefined,
6121    ProtectionDomain protectionDomain,
6122    byte[] binaryRepresentation) {
6123  326 return transform(JavaModule.UNSUPPORTED, classLoader, internalTypeName, classBeingRedefined, protectionDomain, binaryRepresentation);
6124    }
6125   
6126    /**
6127    * Applies a transformation for a class that was captured by this {@link ClassFileTransformer}.
6128    *
6129    * @param rawModule The instrumented class's Java {@code java.lang.reflect.Module}.
6130    * @param internalTypeName The internal name of the instrumented class.
6131    * @param classBeingRedefined The loaded {@link Class} being redefined or {@code null} if no such class exists.
6132    * @param protectionDomain The instrumented type's protection domain.
6133    * @param binaryRepresentation The class file of the instrumented class in its current state.
6134    * @return The transformed class file or an empty byte array if this transformer does not apply an instrumentation.
6135    */
 
6136  0 toggle protected byte[] transform(Object rawModule,
6137    String internalTypeName,
6138    Class<?> classBeingRedefined,
6139    ProtectionDomain protectionDomain,
6140    byte[] binaryRepresentation) {
6141  0 JavaModule module = JavaModule.of(rawModule);
6142  0 return transform(module,
6143    module.getClassLoader(accessControlContext),
6144    internalTypeName,
6145    classBeingRedefined,
6146    protectionDomain,
6147    binaryRepresentation);
6148    }
6149   
6150    /**
6151    * Applies a transformation for a class that was captured by this {@link ClassFileTransformer}.
6152    *
6153    * @param module The instrumented class's Java module in its wrapped form or {@code null} if the current VM does not support modules.
6154    * @param classLoader The instrumented class's class loader.
6155    * @param internalTypeName The internal name of the instrumented class.
6156    * @param classBeingRedefined The loaded {@link Class} being redefined or {@code null} if no such class exists.
6157    * @param protectionDomain The instrumented type's protection domain.
6158    * @param binaryRepresentation The class file of the instrumented class in its current state.
6159    * @return The transformed class file or an empty byte array if this transformer does not apply an instrumentation.
6160    */
 
6161  326 toggle private byte[] transform(JavaModule module,
6162    ClassLoader classLoader,
6163    String internalTypeName,
6164    Class<?> classBeingRedefined,
6165    ProtectionDomain protectionDomain,
6166    byte[] binaryRepresentation) {
6167  326 if (internalTypeName == null) {
6168  44 return NO_TRANSFORMATION;
6169    }
6170  282 String binaryTypeName = internalTypeName.replace('/', '.');
6171  282 try {
6172  282 ClassFileLocator classFileLocator = ClassFileLocator.Simple.of(binaryTypeName,
6173    binaryRepresentation,
6174    ClassFileLocator.ForClassLoader.of(classLoader));
6175  282 return transformation.resolve(descriptionStrategy.apply(binaryTypeName, classBeingRedefined, typeLocator, classLoader, classFileLocator),
6176    classLoader,
6177    module,
6178    classBeingRedefined,
6179    protectionDomain,
6180    ignoredTypeMatcher).apply(initializationStrategy,
6181    classFileLocator,
6182    typeStrategy,
6183    byteBuddy,
6184    nativeMethodStrategy,
6185    bootstrapInjectionStrategy,
6186    accessControlContext,
6187    listener);
6188    } catch (Throwable throwable) {
6189  2 listener.onError(binaryTypeName, classLoader, module, throwable);
6190  2 return NO_TRANSFORMATION;
6191    } finally {
6192  282 listener.onComplete(binaryTypeName, classLoader, module);
6193    }
6194    }
6195   
 
6196  15 toggle @Override
6197    public boolean equals(Object other) {
6198  1 if (this == other) return true;
6199  2 if (other == null || getClass() != other.getClass()) return false;
6200  12 ExecutingTransformer that = (ExecutingTransformer) other;
6201  12 return byteBuddy.equals(that.byteBuddy)
6202    && typeLocator.equals(that.typeLocator)
6203    && typeStrategy.equals(that.typeStrategy)
6204    && initializationStrategy.equals(that.initializationStrategy)
6205    && listener.equals(that.listener)
6206    && nativeMethodStrategy.equals(that.nativeMethodStrategy)
6207    && bootstrapInjectionStrategy.equals(that.bootstrapInjectionStrategy)
6208    && descriptionStrategy.equals(that.descriptionStrategy)
6209    && accessControlContext.equals(that.accessControlContext)
6210    && ignoredTypeMatcher.equals(that.ignoredTypeMatcher)
6211    && transformation.equals(that.transformation);
6212    }
6213   
 
6214  85 toggle @Override
6215    public int hashCode() {
6216  85 int result = byteBuddy.hashCode();
6217  85 result = 31 * result + typeLocator.hashCode();
6218  85 result = 31 * result + typeStrategy.hashCode();
6219  85 result = 31 * result + initializationStrategy.hashCode();
6220  85 result = 31 * result + listener.hashCode();
6221  85 result = 31 * result + nativeMethodStrategy.hashCode();
6222  85 result = 31 * result + bootstrapInjectionStrategy.hashCode();
6223  85 result = 31 * result + descriptionStrategy.hashCode();
6224  85 result = 31 * result + accessControlContext.hashCode();
6225  85 result = 31 * result + ignoredTypeMatcher.hashCode();
6226  85 result = 31 * result + transformation.hashCode();
6227  85 return result;
6228    }
6229   
 
6230  13 toggle @Override
6231    public String toString() {
6232  13 return "AgentBuilder.Default.ExecutingTransformer{" +
6233    "byteBuddy=" + byteBuddy +
6234    ", typeLocator=" + typeLocator +
6235    ", typeStrategy=" + typeStrategy +
6236    ", initializationStrategy=" + initializationStrategy +
6237    ", listener=" + listener +
6238    ", nativeMethodStrategy=" + nativeMethodStrategy +
6239    ", bootstrapInjectionStrategy=" + bootstrapInjectionStrategy +
6240    ", descriptionStrategy=" + descriptionStrategy +
6241    ", accessControlContext=" + accessControlContext +
6242    ", ignoredTypeMatcher=" + ignoredTypeMatcher +
6243    ", transformation=" + transformation +
6244    '}';
6245    }
6246   
6247    /**
6248    * A factory for creating a {@link ClassFileTransformer} for the current VM.
6249    */
 
6250    protected interface Factory {
6251   
6252    /**
6253    * Creates a new class file transformer for the current VM.
6254    *
6255    * @param byteBuddy The Byte Buddy instance to be used.
6256    * @param typeLocator The type locator to use.
6257    * @param typeStrategy The definition handler to use.
6258    * @param listener The listener to notify on transformations.
6259    * @param nativeMethodStrategy The native method strategy to apply.
6260    * @param accessControlContext The access control context to use for loading classes.
6261    * @param initializationStrategy The initialization strategy to use for transformed types.
6262    * @param bootstrapInjectionStrategy The injection strategy for injecting classes into the bootstrap class loader.
6263    * @param descriptionStrategy The description strategy for resolving type descriptions for types.
6264    * @param ignoredTypeMatcher Identifies types that should not be instrumented.
6265    * @param transformation The transformation object for handling type transformations.
6266    * @return A class file transformer for the current VM that supports the API of the current VM.
6267    */
6268    ClassFileTransformer make(ByteBuddy byteBuddy,
6269    TypeLocator typeLocator,
6270    TypeStrategy typeStrategy,
6271    Listener listener,
6272    NativeMethodStrategy nativeMethodStrategy,
6273    AccessControlContext accessControlContext,
6274    InitializationStrategy initializationStrategy,
6275    BootstrapInjectionStrategy bootstrapInjectionStrategy,
6276    DescriptionStrategy descriptionStrategy,
6277    RawMatcher ignoredTypeMatcher,
6278    Transformation transformation);
6279   
6280    /**
6281    * A factory for a class file transformer on a JVM that supports the {@code java.lang.reflect.Module} API to override
6282    * the newly added method of the {@link ClassFileTransformer} to capture an instrumented class's module.
6283    */
 
6284    class ForJava9CapableVm implements Factory {
6285   
6286    /**
6287    * A constructor for creating a {@link ClassFileTransformer} that overrides the newly added method for extracting
6288    * the {@code java.lang.reflect.Module} of an instrumented class.
6289    */
6290    private final Constructor<? extends ClassFileTransformer> executingTransformer;
6291   
6292    /**
6293    * Creates a class file transformer factory for a Java 9 capable VM.
6294    *
6295    * @param executingTransformer A constructor for creating a {@link ClassFileTransformer} that overrides the newly added
6296    * method for extracting the {@code java.lang.reflect.Module} of an instrumented class.
6297    */
 
6298  4 toggle protected ForJava9CapableVm(Constructor<? extends ClassFileTransformer> executingTransformer) {
6299  4 this.executingTransformer = executingTransformer;
6300    }
6301   
 
6302  153 toggle @Override
6303    public ClassFileTransformer make(ByteBuddy byteBuddy,
6304    TypeLocator typeLocator,
6305    TypeStrategy typeStrategy,
6306    Listener listener,
6307    NativeMethodStrategy nativeMethodStrategy,
6308    AccessControlContext accessControlContext,
6309    InitializationStrategy initializationStrategy,
6310    BootstrapInjectionStrategy bootstrapInjectionStrategy,
6311    DescriptionStrategy descriptionStrategy,
6312    RawMatcher ignoredTypeMatcher,
6313    Transformation transformation) {
6314  153 try {
6315  153 return executingTransformer.newInstance(byteBuddy,
6316    typeLocator,
6317    typeStrategy,
6318    listener,
6319    nativeMethodStrategy,
6320    accessControlContext,
6321    initializationStrategy,
6322    bootstrapInjectionStrategy,
6323    descriptionStrategy,
6324    ignoredTypeMatcher,
6325    transformation);
6326    } catch (IllegalAccessException exception) {
6327  0 throw new IllegalStateException("Cannot access " + executingTransformer, exception);
6328    } catch (InstantiationException exception) {
6329  0 throw new IllegalStateException("Cannot instantiate " + executingTransformer.getDeclaringClass(), exception);
6330    } catch (InvocationTargetException exception) {
6331  0 throw new IllegalStateException("Cannot invoke " + executingTransformer, exception.getCause());
6332    }
6333    }
6334   
 
6335  5 toggle @Override
6336    public boolean equals(Object object) {
6337  1 if (this == object) return true;
6338  2 if (object == null || getClass() != object.getClass()) return false;
6339  2 ForJava9CapableVm that = (ForJava9CapableVm) object;
6340  2 return executingTransformer.equals(that.executingTransformer);
6341    }
6342   
 
6343  3 toggle @Override
6344    public int hashCode() {
6345  3 return executingTransformer.hashCode();
6346    }
6347   
 
6348  3 toggle @Override
6349    public String toString() {
6350  3 return "AgentBuilder.Default.ExecutingTransformer.Factory.ForJava9CapableVm{" +
6351    "executingTransformer=" + executingTransformer +
6352    '}';
6353    }
6354    }
6355   
6356    /**
6357    * A factory for a {@link ClassFileTransformer} on a VM that does not support the {@code java.lang.reflect.Module} API.
6358    */
 
6359    enum ForLegacyVm implements Factory {
6360   
6361    /**
6362    * The singleton instance.
6363    */
6364    INSTANCE;
6365   
 
6366  0 toggle @Override
6367    public ClassFileTransformer make(ByteBuddy byteBuddy,
6368    TypeLocator typeLocator,
6369    TypeStrategy typeStrategy,
6370    Listener listener,
6371    NativeMethodStrategy nativeMethodStrategy,
6372    AccessControlContext accessControlContext,
6373    InitializationStrategy initializationStrategy,
6374    BootstrapInjectionStrategy bootstrapInjectionStrategy,
6375    DescriptionStrategy descriptionStrategy,
6376    RawMatcher ignoredTypeMatcher,
6377    Transformation transformation) {
6378  0 return new ExecutingTransformer(byteBuddy,
6379    typeLocator,
6380    typeStrategy,
6381    listener,
6382    nativeMethodStrategy,
6383    accessControlContext,
6384    initializationStrategy,
6385    bootstrapInjectionStrategy,
6386    descriptionStrategy,
6387    ignoredTypeMatcher,
6388    transformation);
6389    }
6390   
 
6391  1 toggle @Override
6392    public String toString() {
6393  1 return "AgentBuilder.Default.ExecutingTransformer.Factory.ForLegacyVm." + name();
6394    }
6395    }
6396    }
6397    }
6398   
6399    /**
6400    * An abstract implementation of an agent builder that delegates all invocation to another instance.
6401    *
6402    * @param <T> The type that is produced by chaining a matcher.
6403    */
 
6404    protected abstract class Delegator<T extends Matchable<T>> extends Matchable.AbstractBase<T> implements AgentBuilder {
6405   
6406    /**
6407    * Materializes the currently described {@link net.bytebuddy.agent.builder.AgentBuilder}.
6408    *
6409    * @return An agent builder that represents the currently described entry of this instance.
6410    */
6411    protected abstract AgentBuilder materialize();
6412   
 
6413  0 toggle @Override
6414    public AgentBuilder with(ByteBuddy byteBuddy) {
6415  0 return materialize().with(byteBuddy);
6416    }
6417   
 
6418  0 toggle @Override
6419    public AgentBuilder with(Listener listener) {
6420  0 return materialize().with(listener);
6421    }
6422   
 
6423  0 toggle @Override
6424    public AgentBuilder with(TypeStrategy typeStrategy) {
6425  0 return materialize().with(typeStrategy);
6426    }
6427   
 
6428  0 toggle @Override
6429    public AgentBuilder with(TypeLocator typeLocator) {
6430  0 return materialize().with(typeLocator);
6431    }
6432   
 
6433  0 toggle @Override
6434    public AgentBuilder with(AccessControlContext accessControlContext) {
6435  0 return materialize().with(accessControlContext);
6436    }
6437   
 
6438  48 toggle @Override
6439    public AgentBuilder with(InitializationStrategy initializationStrategy) {
6440  48 return materialize().with(initializationStrategy);
6441    }
6442   
 
6443  0 toggle @Override
6444    public AgentBuilder with(RedefinitionStrategy redefinitionStrategy) {
6445  0 return materialize().with(redefinitionStrategy);
6446    }
6447   
 
6448  36 toggle @Override
6449    public AgentBuilder with(LambdaInstrumentationStrategy lambdaInstrumentationStrategy) {
6450  36 return materialize().with(lambdaInstrumentationStrategy);
6451    }
6452   
 
6453  0 toggle @Override
6454    public AgentBuilder with(DescriptionStrategy descriptionStrategy) {
6455  0 return materialize().with(descriptionStrategy);
6456    }
6457   
 
6458  0 toggle @Override
6459    public AgentBuilder with(InstallationStrategy installationStrategy) {
6460  0 return materialize().with(installationStrategy);
6461    }
6462   
 
6463  0 toggle @Override
6464    public AgentBuilder enableBootstrapInjection(Instrumentation instrumentation, File folder) {
6465  0 return materialize().enableBootstrapInjection(instrumentation, folder);
6466    }
6467   
 
6468  0 toggle @Override
6469    public AgentBuilder disableBootstrapInjection() {
6470  0 return materialize().disableBootstrapInjection();
6471    }
6472   
 
6473  0 toggle @Override
6474    public AgentBuilder enableNativeMethodPrefix(String prefix) {
6475  0 return materialize().enableNativeMethodPrefix(prefix);
6476    }
6477   
 
6478  0 toggle @Override
6479    public AgentBuilder disableNativeMethodPrefix() {
6480  0 return materialize().disableNativeMethodPrefix();
6481    }
6482   
 
6483  0 toggle @Override
6484    public AgentBuilder disableClassFormatChanges() {
6485  0 return materialize().disableClassFormatChanges();
6486    }
6487   
 
6488  0 toggle @Override
6489    public AgentBuilder assureReadEdgeTo(Instrumentation instrumentation, Class<?>... type) {
6490  0 return materialize().assureReadEdgeTo(instrumentation, type);
6491    }
6492   
 
6493  0 toggle @Override
6494    public AgentBuilder assureReadEdgeTo(Instrumentation instrumentation, JavaModule... module) {
6495  0 return materialize().assureReadEdgeTo(instrumentation, module);
6496    }
6497   
 
6498  0 toggle @Override
6499    public AgentBuilder assureReadEdgeTo(Instrumentation instrumentation, Collection<? extends JavaModule> modules) {
6500  0 return materialize().assureReadEdgeTo(instrumentation, modules);
6501    }
6502   
 
6503  0 toggle @Override
6504    public AgentBuilder assureReadEdgeFromAndTo(Instrumentation instrumentation, Class<?>... type) {
6505  0 return materialize().assureReadEdgeFromAndTo(instrumentation, type);
6506    }
6507   
 
6508  0 toggle @Override
6509    public AgentBuilder assureReadEdgeFromAndTo(Instrumentation instrumentation, JavaModule... module) {
6510  0 return materialize().assureReadEdgeFromAndTo(instrumentation, module);
6511    }
6512   
 
6513  0 toggle @Override
6514    public AgentBuilder assureReadEdgeFromAndTo(Instrumentation instrumentation, Collection<? extends JavaModule> modules) {
6515  0 return materialize().assureReadEdgeFromAndTo(instrumentation, modules);
6516    }
6517   
 
6518  2 toggle @Override
6519    public Identified.Narrowable type(ElementMatcher<? super TypeDescription> typeMatcher) {
6520  2 return materialize().type(typeMatcher);
6521    }
6522   
 
6523  44 toggle @Override
6524    public Identified.Narrowable type(ElementMatcher<? super TypeDescription> typeMatcher, ElementMatcher<? super ClassLoader> classLoaderMatcher) {
6525  44 return materialize().type(typeMatcher, classLoaderMatcher);
6526    }
6527   
 
6528  0 toggle @Override
6529    public Identified.Narrowable type(ElementMatcher<? super TypeDescription> typeMatcher,
6530    ElementMatcher<? super ClassLoader> classLoaderMatcher,
6531    ElementMatcher<? super JavaModule> moduleMatcher) {
6532  0 return materialize().type(typeMatcher, classLoaderMatcher, moduleMatcher);
6533    }
6534   
6535   
 
6536  26 toggle @Override
6537    public Identified.Narrowable type(RawMatcher matcher) {
6538  26 return materialize().type(matcher);
6539    }
6540   
 
6541  0 toggle @Override
6542    public Ignored ignore(ElementMatcher<? super TypeDescription> ignoredTypes) {
6543  0 return materialize().ignore(ignoredTypes);
6544    }
6545   
 
6546  0 toggle @Override
6547    public Ignored ignore(ElementMatcher<? super TypeDescription> ignoredTypes, ElementMatcher<? super ClassLoader> ignoredClassLoaders) {
6548  0 return materialize().ignore(ignoredTypes, ignoredClassLoaders);
6549    }
6550   
 
6551  0 toggle @Override
6552    public Ignored ignore(ElementMatcher<? super TypeDescription> typeMatcher,
6553    ElementMatcher<? super ClassLoader> classLoaderMatcher,
6554    ElementMatcher<? super JavaModule> moduleMatcher) {
6555  0 return materialize().ignore(typeMatcher, classLoaderMatcher, moduleMatcher);
6556    }
6557   
 
6558  0 toggle @Override
6559    public Ignored ignore(RawMatcher rawMatcher) {
6560  0 return materialize().ignore(rawMatcher);
6561    }
6562   
 
6563  0 toggle @Override
6564    public ClassFileTransformer makeRaw() {
6565  0 return materialize().makeRaw();
6566    }
6567   
 
6568  61 toggle @Override
6569    public ClassFileTransformer installOn(Instrumentation instrumentation) {
6570  61 return materialize().installOn(instrumentation);
6571    }
6572   
 
6573  68 toggle @Override
6574    public ClassFileTransformer installOnByteBuddyAgent() {
6575  68 return materialize().installOnByteBuddyAgent();
6576    }
6577    }
6578   
6579    /**
6580    * A delegator transformer for further precising what types to ignore.
6581    */
 
6582    protected class Ignoring extends Delegator<Ignored> implements Ignored {
6583   
6584    /**
6585    * A matcher for identifying types that should not be instrumented.
6586    */
6587    private final RawMatcher rawMatcher;
6588   
6589    /**
6590    * Creates a new agent builder for further specifying what types to ignore.
6591    *
6592    * @param rawMatcher A matcher for identifying types that should not be instrumented.
6593    */
 
6594  149 toggle protected Ignoring(RawMatcher rawMatcher) {
6595  149 this.rawMatcher = rawMatcher;
6596    }
6597   
 
6598  143 toggle @Override
6599    protected AgentBuilder materialize() {
6600  143 return new Default(byteBuddy,
6601    typeLocator,
6602    typeStrategy,
6603    listener,
6604    nativeMethodStrategy,
6605    accessControlContext,
6606    initializationStrategy,
6607    redefinitionStrategy,
6608    bootstrapInjectionStrategy,
6609    lambdaInstrumentationStrategy,
6610    descriptionStrategy,
6611    installationStrategy,
6612    rawMatcher,
6613    transformation);
6614    }
6615   
 
6616  1 toggle @Override
6617    public Ignored and(RawMatcher rawMatcher) {
6618  1 return new Ignoring(new RawMatcher.Conjunction(this.rawMatcher, rawMatcher));
6619    }
6620   
 
6621  1 toggle @Override
6622    public Ignored or(RawMatcher rawMatcher) {
6623  1 return new Ignoring(new RawMatcher.Disjunction(this.rawMatcher, rawMatcher));
6624    }
6625   
6626    /**
6627    * Returns the outer instance.
6628    *
6629    * @return The outer instance.
6630    */
 
6631  2 toggle private Default getOuter() {
6632  2 return Default.this;
6633    }
6634   
 
6635  6 toggle @Override
6636    public boolean equals(Object other) {
6637  6 return this == other || !(other == null || getClass() != other.getClass())
6638    && rawMatcher.equals(((Ignoring) other).rawMatcher)
6639    && Default.this.equals(((Ignoring) other).getOuter());
6640    }
6641   
 
6642  4 toggle @Override
6643    public int hashCode() {
6644  4 int result = rawMatcher.hashCode();
6645  4 result = 31 * result + Default.this.hashCode();
6646  4 return result;
6647    }
6648   
 
6649  5 toggle @Override
6650    public String toString() {
6651  5 return "AgentBuilder.Default.Ignoring{" +
6652    "rawMatcher=" + rawMatcher +
6653    ", agentBuilder=" + Default.this +
6654    '}';
6655    }
6656    }
6657   
6658    /**
6659    * A helper class that describes a {@link net.bytebuddy.agent.builder.AgentBuilder.Default} after supplying
6660    * a {@link net.bytebuddy.agent.builder.AgentBuilder.RawMatcher} such that one or several
6661    * {@link net.bytebuddy.agent.builder.AgentBuilder.Transformer}s can be supplied.
6662    */
 
6663    protected class Transforming extends Delegator<Identified.Narrowable> implements Identified.Extendable, Identified.Narrowable {
6664   
6665    /**
6666    * The supplied raw matcher.
6667    */
6668    private final RawMatcher rawMatcher;
6669   
6670    /**
6671    * The supplied transformer.
6672    */
6673    private final Transformer transformer;
6674   
6675    /**
6676    * {@code true} if this transformer serves as a decorator.
6677    */
6678    private final boolean decorator;
6679   
6680    /**
6681    * Creates a new matched default agent builder.
6682    *
6683    * @param rawMatcher The supplied raw matcher.
6684    * @param transformer The supplied transformer.
6685    * @param decorator {@code true} if this transformer serves as a decorator.
6686    */
 
6687  301 toggle protected Transforming(RawMatcher rawMatcher, Transformer transformer, boolean decorator) {
6688  301 this.rawMatcher = rawMatcher;
6689  301 this.transformer = transformer;
6690  301 this.decorator = decorator;
6691    }
6692   
 
6693  142 toggle @Override
6694    protected AgentBuilder materialize() {
6695  142 return new Default(byteBuddy,
6696    typeLocator,
6697    typeStrategy,
6698    listener,
6699    nativeMethodStrategy,
6700    accessControlContext,
6701    initializationStrategy,
6702    redefinitionStrategy,
6703    bootstrapInjectionStrategy,
6704    lambdaInstrumentationStrategy,
6705    descriptionStrategy,
6706    installationStrategy,
6707    ignoredTypeMatcher,
6708    new Transformation.Compound(new Transformation.Simple(rawMatcher, transformer, decorator), transformation));
6709    }
6710   
 
6711  138 toggle @Override
6712    public Identified.Extendable transform(Transformer transformer) {
6713  138 return new Transforming(rawMatcher, new Transformer.Compound(this.transformer, transformer), decorator);
6714    }
6715   
 
6716  17 toggle @Override
6717    public AgentBuilder asDecorator() {
6718  17 return new Transforming(rawMatcher, transformer, true);
6719    }
6720   
 
6721  1 toggle @Override
6722    public Narrowable and(RawMatcher rawMatcher) {
6723  1 return new Transforming(new RawMatcher.Conjunction(this.rawMatcher, rawMatcher), transformer, decorator);
6724    }
6725   
 
6726  1 toggle @Override
6727    public Narrowable or(RawMatcher rawMatcher) {
6728  1 return new Transforming(new RawMatcher.Disjunction(this.rawMatcher, rawMatcher), transformer, decorator);
6729    }
6730   
6731    /**
6732    * Returns the outer instance.
6733    *
6734    * @return The outer instance.
6735    */
 
6736  2 toggle private Default getOuter() {
6737  2 return Default.this;
6738    }
6739   
 
6740  8 toggle @Override
6741    public boolean equals(Object other) {
6742  8 return this == other || !(other == null || getClass() != other.getClass())
6743    && decorator == ((Transforming) other).decorator
6744    && rawMatcher.equals(((Transforming) other).rawMatcher)
6745    && transformer.equals(((Transforming) other).transformer)
6746    && Default.this.equals(((Transforming) other).getOuter());
6747    }
6748   
 
6749  6 toggle @Override
6750    public int hashCode() {
6751  6 int result = rawMatcher.hashCode();
6752  6 result = 31 * result + (decorator ? 1 : 0);
6753  6 result = 31 * result + transformer.hashCode();
6754  6 result = 31 * result + Default.this.hashCode();
6755  6 return result;
6756    }
6757   
 
6758  11 toggle @Override
6759    public String toString() {
6760  11 return "AgentBuilder.Default.Transforming{" +
6761    "rawMatcher=" + rawMatcher +
6762    ", transformer=" + transformer +
6763    ", decorator=" + decorator +
6764    ", agentBuilder=" + Default.this +
6765    '}';
6766    }
6767    }
6768    }
6769    }